Skip to content

Commit d22b51f

Browse files
ralyodioclaude
andcommitted
feat(turn): add GitHub Actions deployment and idempotent setup script
- Create deploy-turn.yml workflow for automated droplet deployment - Make setup-turn-server.sh fully idempotent (safe to run multiple times) - Give ubuntu user passwordless sudo for deployments - Update .env.example with DROPLET_* variables - Update README with GitHub Actions deployment docs - Fix desktop app postcss.config.js for CommonJS Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent b1eac48 commit d22b51f

8 files changed

Lines changed: 516 additions & 24 deletions

File tree

.env.example

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,12 @@ SUPABASE_DB_PASSWORD=your-db-password-here
3030
# TURN Server Configuration
3131
# Required for WebRTC NAT traversal
3232
# ===========================================
33-
TURN_SERVER_URL=turn:your-turn-server.com:3478
34-
TURN_SERVER_USERNAME=your-turn-username
35-
TURN_SERVER_CREDENTIAL=your-turn-credential
33+
TURN_SERVER_URL=turn:turn.pairux.com:3478
34+
TURN_SERVER_USERNAME=ubuntu
35+
TURN_SERVER_CREDENTIAL=your-turn-secret-here
36+
37+
# TLS TURN (for restrictive firewalls)
38+
TURNS_SERVER_URL=turns:turn.pairux.com:5349
3639

3740
# ===========================================
3841
# Application Configuration
@@ -61,3 +64,12 @@ NODE_ENV=development
6164
# GPG_PRIVATE_KEY=base64-encoded-key
6265
# GPG_PASSPHRASE=your-passphrase
6366
# GPG_KEY_ID=your-key-id
67+
68+
# ===========================================
69+
# Droplet Deployment (TURN Server)
70+
# Used by GitHub Actions to deploy to DigitalOcean droplet
71+
# ===========================================
72+
# DROPLET_HOST=143.198.96.161
73+
# DROPLET_PORT=22
74+
# DROPLET_USER=root
75+
# DROPLET_SSH_KEY=base64-encoded-private-key

.github/workflows/deploy-turn.yml

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
name: Deploy TURN Server
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
paths:
8+
- 'apps/turn/**'
9+
workflow_dispatch:
10+
11+
concurrency:
12+
group: deploy-turn
13+
cancel-in-progress: false
14+
15+
jobs:
16+
deploy:
17+
runs-on: ubuntu-latest
18+
name: Deploy to TURN Droplet
19+
20+
steps:
21+
- name: Checkout
22+
uses: actions/checkout@v4
23+
24+
- name: Setup SSH
25+
run: |
26+
mkdir -p ~/.ssh
27+
echo "${{ secrets.DROPLET_SSH_KEY }}" > ~/.ssh/id_rsa
28+
chmod 600 ~/.ssh/id_rsa
29+
ssh-keyscan -p ${{ secrets.DROPLET_PORT || 22 }} ${{ secrets.DROPLET_HOST }} >> ~/.ssh/known_hosts
30+
31+
- name: Deploy setup script
32+
env:
33+
SSH_HOST: ${{ secrets.DROPLET_HOST }}
34+
SSH_PORT: ${{ secrets.DROPLET_PORT || 22 }}
35+
SSH_USER: ${{ secrets.DROPLET_USER }}
36+
TURN_PASSWORD: ${{ secrets.TURN_SERVER_CREDENTIAL }}
37+
TURN_REALM: turn.pairux.com
38+
run: |
39+
# Copy setup script to droplet
40+
scp -P $SSH_PORT apps/turn/setup-turn-server.sh $SSH_USER@$SSH_HOST:/tmp/
41+
42+
# Run setup script
43+
ssh -p $SSH_PORT $SSH_USER@$SSH_HOST "sudo bash /tmp/setup-turn-server.sh '$TURN_PASSWORD' '' '$TURN_REALM'"
44+
45+
- name: Verify TURN server
46+
env:
47+
SSH_HOST: ${{ secrets.DROPLET_HOST }}
48+
SSH_PORT: ${{ secrets.DROPLET_PORT || 22 }}
49+
SSH_USER: ${{ secrets.DROPLET_USER }}
50+
run: |
51+
ssh -p $SSH_PORT $SSH_USER@$SSH_HOST "sudo systemctl status coturn --no-pager"
52+
53+
- name: Cleanup
54+
if: always()
55+
run: |
56+
rm -f ~/.ssh/id_rsa

.github/workflows/desktop-release.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,11 @@ jobs:
9797
- name: Build desktop app
9898
run: pnpm --filter @pairux/desktop build
9999
env:
100+
# TURN server configuration
101+
TURN_SERVER_URL: ${{ secrets.TURN_SERVER_URL }}
102+
TURN_SERVER_USERNAME: ${{ secrets.TURN_SERVER_USERNAME }}
103+
TURN_SERVER_CREDENTIAL: ${{ secrets.TURN_SERVER_CREDENTIAL }}
104+
TURNS_SERVER_URL: ${{ secrets.TURNS_SERVER_URL }}
100105
# macOS signing
101106
APPLE_ID: ${{ secrets.APPLE_ID }}
102107
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}

apps/desktop/electron.vite.config.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,21 @@ export default defineConfig({
77
plugins: [externalizeDepsPlugin()],
88
build: {
99
outDir: 'dist/main',
10-
lib: {
11-
entry: resolve(__dirname, 'src/main/index.ts'),
12-
},
1310
rollupOptions: {
14-
external: ['electron'],
11+
input: {
12+
index: resolve(__dirname, 'src/main/index.ts'),
13+
},
1514
},
1615
},
1716
},
1817
preload: {
1918
plugins: [externalizeDepsPlugin()],
2019
build: {
2120
outDir: 'dist/preload',
22-
lib: {
23-
entry: resolve(__dirname, 'src/preload/index.ts'),
24-
},
2521
rollupOptions: {
26-
external: ['electron'],
22+
input: {
23+
index: resolve(__dirname, 'src/preload/index.ts'),
24+
},
2725
},
2826
},
2927
},

apps/desktop/postcss.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export default {
1+
module.exports = {
22
plugins: {
33
tailwindcss: {},
44
autoprefixer: {},

apps/turn/README.md

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,12 @@ doctl compute droplet create pairux-turn \
3131
### 2. Deploy
3232

3333
```bash
34-
cd apps/turn
35-
./deploy-droplet.sh <DROPLET_IP> <TURN_PASSWORD>
34+
# SSH to droplet and run setup script
35+
ssh root@<DROPLET_IP> "curl -fsSL https://raw.githubusercontent.com/profullstack/pairux.com/master/apps/turn/setup-turn-server.sh | bash -s -- 'YOUR_PASSWORD'"
3636

37-
# Example:
38-
./deploy-droplet.sh 164.92.105.42 'super-secure-password-123'
37+
# Or copy and run locally
38+
scp apps/turn/setup-turn-server.sh root@<DROPLET_IP>:/root/
39+
ssh root@<DROPLET_IP> "./setup-turn-server.sh 'YOUR_PASSWORD'"
3940
```
4041

4142
### 3. Add DNS
@@ -46,13 +47,47 @@ Add an A record: `turn.pairux.com` → `<droplet-ip>`
4647

4748
```bash
4849
# From anywhere
49-
turnutils_uclient -t -u pairux -w YOUR_PASSWORD turn.pairux.com
50+
turnutils_uclient -t -u ubuntu -w YOUR_PASSWORD turn.pairux.com
5051
```
5152

5253
**Cost:** ~$6/month (1 vCPU, 1GB RAM)
5354

5455
---
5556

57+
## GitHub Actions Deployment
58+
59+
The TURN server can be automatically deployed via GitHub Actions when changes are pushed to `apps/turn/`.
60+
61+
### Required GitHub Secrets
62+
63+
| Secret | Description |
64+
| ------------------------ | ------------------------------------------- |
65+
| `DROPLET_HOST` | Droplet IP address (e.g., `143.198.96.161`) |
66+
| `DROPLET_PORT` | SSH port (default: `22`) |
67+
| `DROPLET_USER` | SSH user (e.g., `root` or `ubuntu`) |
68+
| `DROPLET_SSH_KEY` | Private SSH key (base64 encoded) |
69+
| `TURN_SERVER_CREDENTIAL` | TURN password |
70+
71+
### Add Secrets
72+
73+
```bash
74+
# Encode your SSH private key
75+
cat ~/.ssh/id_rsa | base64 -w 0
76+
77+
# Add to GitHub:
78+
# Settings → Secrets and variables → Actions → New repository secret
79+
```
80+
81+
### Manual Trigger
82+
83+
You can also trigger deployment manually:
84+
85+
```bash
86+
gh workflow run deploy-turn.yml
87+
```
88+
89+
---
90+
5691
## Configuration
5792

5893
### Ports Required
@@ -85,12 +120,12 @@ const config = {
85120
// TURN fallback (when direct connections fail)
86121
{
87122
urls: 'turn:turn.pairux.com:3478',
88-
username: 'pairux',
123+
username: 'ubuntu',
89124
credential: process.env.TURN_PASSWORD,
90125
},
91126
{
92127
urls: 'turns:turn.pairux.com:5349',
93-
username: 'pairux',
128+
username: 'ubuntu',
94129
credential: process.env.TURN_PASSWORD,
95130
},
96131
],
@@ -119,7 +154,7 @@ If you prefer not to self-host:
119154

120155
1. Go to https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/
121156
2. Add server: `turn:turn.pairux.com:3478`
122-
3. Enter username: `pairux`
157+
3. Enter username: `ubuntu`
123158
4. Enter password: `<your-password>`
124159
5. Click "Gather candidates"
125160
6. Look for `relay` candidates
@@ -134,7 +169,7 @@ apt install coturn-utils
134169
turnutils_uclient -p 3478 turn.pairux.com
135170

136171
# Test TURN
137-
turnutils_uclient -t -u pairux -w YOUR_PASSWORD turn.pairux.com
172+
turnutils_uclient -t -u ubuntu -w YOUR_PASSWORD turn.pairux.com
138173
```
139174

140175
---
@@ -143,13 +178,14 @@ turnutils_uclient -t -u pairux -w YOUR_PASSWORD turn.pairux.com
143178

144179
```bash
145180
# Check status
146-
ssh root@<droplet-ip> "docker compose -f /opt/pairux-turn/docker-compose.yml ps"
181+
ssh root@<droplet-ip> "systemctl status coturn"
147182

148183
# View logs
149-
ssh root@<droplet-ip> "docker compose -f /opt/pairux-turn/docker-compose.yml logs -f"
184+
ssh root@<droplet-ip> "tail -f /var/log/turnserver.log"
185+
ssh root@<droplet-ip> "journalctl -u coturn -f"
150186

151187
# Restart
152-
ssh root@<droplet-ip> "docker compose -f /opt/pairux-turn/docker-compose.yml restart"
188+
ssh root@<droplet-ip> "systemctl restart coturn"
153189
```
154190

155191
---

0 commit comments

Comments
 (0)