Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(rust): automated deployment to fly.io #91

Merged
merged 9 commits into from
Oct 4, 2023
Merged
17 changes: 17 additions & 0 deletions .github/workflows/deploy-rust-peer.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
on:
push:
branches:
- "main"

jobs:
deploy_to_fly_io:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./rust-peer
steps:
- uses: actions/checkout@v3
- uses: superfly/flyctl-actions/setup-flyctl@master
- run: flyctl deploy --remote-only
env:
FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
24 changes: 3 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,39 +64,21 @@ npm run dev

## Getting started: Rust

### 1. Start your own Rust peer

If you are the first peer in the network, simply run:

```
cd rust-peer
cargo run
```

However, for this repo, we have a rust server already running in the cloud, and you can add your own Rust server peer to the chat network with `cargo run` from the `rust-peer` directory.

To connect your rust peer to the rest of the network, you need to add the remote multiaddress of any peer already running as a the command line argument.
This will automatically connect you to the bootstrap node running on [fly.io](https://fly.io).

Below we have added our already running Rust peer as the arg `remote-address`:
To explore more advanced configurations if you e.g. want to set up our own network, try:

```
cd rust-peer
cargo run -- --remote-address=/ip4/18.195.246.16/udp/9091/quic-v1/p2p/12D3KooWSmtsbL2ukwVwf8gDoTYZHnCd7sVNNVdMnCa4MkWjLujm
cargo run -- --help
```

This will bootstrap your peer to the rest of the network, so you will see all messages sent on the chat topic in your own peer. It needs to connect via `quic-v1` because it works with all servers.

You should see the multiaddr of the peer once its loaded, e.g.

```
Listen address: "/ip4/127.0.0.1/udp/49350/webrtc/certhash/uEiAs1mQgRDVdSqMsQAuEnpMW0sSj6qc5jNvx2d0r3bQoiA/p2p/12D3KooWMzXTNGDLCKy6i6eAgJPMGCxuu7NJz33T9oC5kjByY27W
```


## Getting started: Go

### 1. Start peer

```
cd go-peer
go run .
Expand Down
2 changes: 1 addition & 1 deletion rust-peer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ edition = "2021"

[dependencies]
anyhow = "1.0"
clap = { version = "4.1.11", features = ["derive"] }
clap = { version = "4.1.11", features = ["derive", "env"] }
env_logger = "0.10.0"
futures = "0.3.27"
futures-timer = "3.0.2"
Expand Down
33 changes: 24 additions & 9 deletions rust-peer/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,9 +1,24 @@
FROM rust:1.68 as builder
WORKDIR /usr/src/universal-chat
COPY . .
RUN cargo install --path .

FROM debian:bullseye-slim
RUN apt-get update && apt-get install && rm -rf /var/lib/apt/lists/*
COPY --from=builder /usr/local/cargo/bin/rust-libp2p-webrtc-peer /usr/local/bin/rust-libp2p-webrtc-peer
CMD ["rust-libp2p-webrtc-peer"]
# syntax=docker/dockerfile:1.5-labs
FROM rust:1.72.0 as builder

RUN rustup target add x86_64-unknown-linux-musl
RUN --mount=type=cache,target=/var/cache/apt apt-get update && apt-get install -y musl-dev musl-tools

# Run with access to the target cache to speed up builds
WORKDIR /workspace
ADD . .
RUN --mount=type=cache,target=./target \
--mount=type=cache,target=/usr/local/cargo/registry \
cargo build --release --target x86_64-unknown-linux-musl

RUN --mount=type=cache,target=./target \
mv ./target/x86_64-unknown-linux-musl/release/rust-libp2p-webrtc-peer /usr/local/bin/rust-libp2p-webrtc-peer

FROM alpine:3
WORKDIR /app
COPY --from=builder /usr/local/bin/rust-libp2p-webrtc-peer /usr/bin/rust-libp2p-webrtc-peer
RUN --mount=type=cache,target=/var/cache/apk apk add bind-tools
2color marked this conversation as resolved.
Show resolved Hide resolved

ENV RUST_BACKTRACE=1

CMD ["rust-libp2p-webrtc-peer"]
28 changes: 28 additions & 0 deletions rust-peer/fly.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# fly.toml app configuration file generated for universal-connectivity-rust-peer on 2023-09-24T16:20:25+10:00
#
# See https://fly.io/docs/reference/configuration/ for information about how to use this file.
#

app = "universal-connectivity-rust-peer"
primary_region = "syd"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any thoughts on moving this to Europe/US, where most users will likely be connecting from?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Happy to, this is just the default 😅


[experimental]
# Resolve the special `fly-global-services` address before starting the container, see https://fly.io/docs/app-guides/udp-and-tcp/#the-fly-global-services-address.
cmd = ["/bin/sh", "-c", "set -ex; LISTEN_ADDRESS=$(getent hosts fly-global-services | cut -d' ' -f1) && rust-libp2p-webrtc-peer"]

[env]
EXTERNAL_ADDRESS="149.248.215.31" # TODO: Remove this in favor of an AutoNAT setup.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would AutoNAT even work when deployed to Fly.io? In my experience running Kubo on fly.io, their overlay network messes with AutoNAT and results in the wrong IP, but it's been a while since I actually tried it and I didn't dive too deep.


[[services]]
internal_port = 9090
protocol = "udp"

[[services.ports]]
port = "9090"

[[services]]
internal_port = 9091
protocol = "udp"

[[services.ports]]
port = "9091"
31 changes: 23 additions & 8 deletions rust-peer/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,16 @@ struct Opt {
#[clap(long, default_value = "0.0.0.0")]
listen_address: IpAddr,

/// Address of a remote peer to connect to.
#[clap(long)]
remote_address: Option<Multiaddr>,
/// If known, the external address of this node. Will be used to correctly advertise our external address across all transports.
#[clap(long, env)]
external_address: Option<IpAddr>,

/// Nodes to connect to on startup. Can be specified several times.
#[clap(
long,
default_value = "/dns/universal-connectivity-rust-peer.fly.dev/udp/9091/quic-v1"
)]
connect: Vec<Multiaddr>,
}

/// An example WebRTC peer that will accept connections
Expand Down Expand Up @@ -85,10 +92,10 @@ async fn main() -> Result<()> {
.listen_on(address_quic.clone())
.expect("listen on quic");

if let Some(remote_address) = opt.remote_address {
swarm
.dial(remote_address)
.expect("a valid remote address to be provided");
for addr in opt.connect {
if let Err(e) = swarm.dial(addr.clone()) {
debug!("Failed to dial {addr}: {e}");
}
}

let chat_topic_hash = gossipsub::IdentTopic::new(GOSSIPSUB_CHAT_TOPIC).hash();
Expand All @@ -101,8 +108,16 @@ async fn main() -> Result<()> {
match select(swarm.next(), &mut tick).await {
Either::Left((event, _)) => match event.unwrap() {
SwarmEvent::NewListenAddr { address, .. } => {
if let Some(external_ip) = opt.external_address {
let external_address = address
.replace(0, |_| Some(external_ip.into()))
.expect("address.len > 1 and we always return `Some`");

swarm.add_external_address(external_address);
}

let p2p_address = address.with(Protocol::P2p(*swarm.local_peer_id()));
info!("Listen p2p address: {p2p_address:?}");
info!("Listening on {p2p_address}");
}
SwarmEvent::ConnectionEstablished { peer_id, .. } => {
info!("Connected to {peer_id}");
Expand Down