feat: Host a relay on Hetzner (#114)

We are hosting a [MoQ](https://quic.video) relay on a remote (bare
metal) server on Hetzner

With a lot of help from @victorpahuus
This commit is contained in:
Wanjohi
2024-09-26 21:34:42 +03:00
committed by GitHub
parent c4a6895726
commit bae089e223
74 changed files with 7107 additions and 96 deletions

87
infra/RELAY.md Normal file
View File

@@ -0,0 +1,87 @@
# How to Deploy Your Own MoQ Relay on a Server
This guide will walk you through the steps to deploy your own MoQ relay on a server.
## Prerequisites
1. **Server Requirements:**
- Ensure port 443 is open for both TCP and UDP (`:443/udp & :443/tcp`).
- The server should have a minimum of **4GB RAM** and **2 vCPUs**.
- Supports ARM or AMD64 architecture.
2. **Software Requirements:**
- Docker and `docker-compose` must be installed on the server. You can use [this installation script](https://github.com/docker/docker-install) for Docker.
- Git must be installed to clone the necessary repository.
3. **Certificates:**
- You will need private and public certificates. It is recommended to use certificates from a trusted CA rather than self-signed certificates.
## Installation Steps
### Step 1: Clone the Repository
Clone the `kixelated/moq-rs` repository to your local machine:
```bash
git clone https://github.com/kixelated/moq-rs moq
```
### Step 2: Verify Port Availability
Check if port 443 is already in use on your server:
```bash
sudo netstat -tulpn | grep ':443' | grep LISTEN
```
or
```bash
sudo lsof -i -P -n | grep LISTEN | grep 443
```
If you find any processes using port 443, consider terminating them.
### Step 3: Configure Ports
Navigate to the cloned directory and edit the Docker compose file to use port 443:
```bash
cd moq
vim docker-compose.yml
```
Change the ports section from lines 34 to 35 to:
```yaml
ports:
- "443:443"
- "443:443/udp"
```
### Step 4: Prepare Certificates
Copy your generated certificates into the `moq/dev` directory and rename them:
```bash
cp cert.pem moq/dev/localhost.crt
cp key.pem moq/dev/localhost.key
```
### Step 5: Start Docker Instances
Ensure you are in the root directory of the `moq` project, then start the Docker containers:
```bash
docker compose up -d
```
### Step 6: Link Domain to Server IP
Configure your DNS settings to connect your server's IP address to your domain:
```
Record Type: A
Subdomain: relay.fst.so
IP Address: xx.xxx.xx.xxx
```
Congratulations, your MoQ server is now set up! You can verify its functionality by using the [MoQ Checker](https://nestri.pages.dev/moq/checker).

View File

@@ -1,9 +1,9 @@
export const domain =
{
production: "fst.so",
dev: "dev.fst.so",
}[$app.stage] || $app.stage + ".dev.fst.so";
// export const domain =
// {
// production: "fst.so",
// dev: "dev.fst.so",
// }[$app.stage] || $app.stage + ".dev.fst.so";
export const zone = cloudflare.getZoneOutput({
name: "fst.so",
});
// export const zone = cloudflare.getZoneOutput({
// name: "fst.so",
// });

View File

@@ -1,38 +0,0 @@
import { isPermanentStage } from "./stage";
if (isPermanentStage) {
const github = new aws.iam.OpenIdConnectProvider("GithubProvider", {
url: "https://token.actions.githubusercontent.com",
clientIdLists: ["sts.amazonaws.com"],
thumbprintLists: [
"6938fd4d98bab03faadb97b34396831e3780aea1",
"1c58a3a8518e8759bf075b76b750d4f2df264fcd",
],
});
const githubRole = new aws.iam.Role("GithubRole", {
name: [$app.name, $app.stage, "github"].join("-"),
assumeRolePolicy: {
Version: "2012-10-17",
Statement: [
{
Effect: "Allow",
Principal: {
Federated: github.arn,
},
Action: "sts:AssumeRoleWithWebIdentity",
Condition: {
StringLike: github.url.apply((url) => ({
[`${url}:sub`]: "repo:nestriness/nestri:*",
})),
},
},
],
},
});
new aws.iam.RolePolicyAttachment("GithubRolePolicy", {
policyArn: "arn:aws:iam::aws:policy/AdministratorAccess",
role: githubRole.name,
});
}

22
infra/relay.ts Normal file
View File

@@ -0,0 +1,22 @@
import { resolve as pathResolve } from "node:path";
import { readFileSync as readFile } from "node:fs";
//Copy your (known) ssh public key to the remote machine
//ssh-copy-id "-p $port" user@host
const domain = "fst.so"
const ips = ["95.216.29.238"]
// Get the hosted zone
const zone = aws.route53.getZone({ name: domain });
// Create an A record
const record = new aws.route53.Record("Relay DNS Records", {
zoneId: zone.then(zone => zone.zoneId),
type: "A",
name: `relay.${domain}`,
ttl: 300,
records: ips,
});
// Export the URL
export const url = $interpolate`https://${record.name}`;