Skip to main content

max / makenotwork

6.3 KB · 168 lines History Blame Raw
1 #!/bin/bash
2 # Makenotwork Deployment Script
3 # Cross-compiles for x86_64 Linux on macOS, uploads everything, restarts services.
4 # Run from the MNW/server directory.
5 #
6 # Usage:
7 # ./deploy/deploy.sh # Full deploy (build + upload + config + restart)
8 # ./deploy/deploy.sh --quick # Quick deploy (build + upload binary + restart app)
9 # ./deploy/deploy.sh --config # Config only (upload Caddyfile, systemd, error pages, backup script)
10 #
11 # Prerequisites (one-time):
12 # brew install zig
13 # cargo install cargo-zigbuild
14 # rustup target add x86_64-unknown-linux-gnu
15
16 set -e
17
18 # Configuration
19 SERVER="root@100.120.174.96"
20 SSH_PORT=2200
21 SSH_OPTS="-p $SSH_PORT"
22 SCP_OPTS="-P $SSH_PORT"
23 REMOTE_DIR="/opt/makenotwork"
24 BINARY_NAME="makenotwork"
25 TARGET="x86_64-unknown-linux-gnu"
26 DEPLOY_DIR="deploy"
27
28 # Check we're in the right directory
29 if [ ! -f "Cargo.toml" ]; then
30 echo "Error: Run this script from the MNW/server directory"
31 exit 1
32 fi
33
34 upload_config() {
35 echo "[config] Uploading configuration files..."
36 scp $SCP_OPTS $DEPLOY_DIR/Caddyfile $SERVER:/etc/caddy/Caddyfile
37 scp $SCP_OPTS $DEPLOY_DIR/makenotwork.service $SERVER:/etc/systemd/system/makenotwork.service
38 scp $SCP_OPTS $DEPLOY_DIR/backup-db.sh $SERVER:$REMOTE_DIR/backup-db.sh
39 ssh $SSH_OPTS $SERVER "chmod +x $REMOTE_DIR/backup-db.sh"
40
41 # Error pages
42 ssh $SSH_OPTS $SERVER "mkdir -p $REMOTE_DIR/error-pages"
43 scp $SCP_OPTS $DEPLOY_DIR/error-pages/*.html $SERVER:$REMOTE_DIR/error-pages/
44
45 # Git SSH and security config files
46 ssh $SSH_OPTS $SERVER "mkdir -p $REMOTE_DIR/deploy"
47 scp $SCP_OPTS $DEPLOY_DIR/sshd-git.conf $DEPLOY_DIR/fail2ban-sshd.conf $DEPLOY_DIR/setup-firewall.sh $SERVER:$REMOTE_DIR/deploy/
48 scp $SCP_OPTS $DEPLOY_DIR/setup-git-ssh.sh $DEPLOY_DIR/setup-ssh-keys.sh $SERVER:$REMOTE_DIR/deploy/ 2>/dev/null || true
49 # Scan-pipeline setup scripts (one-time, manually run on prod). See
50 # docs/scan-pipeline-audit.md § 8 for the rollout procedure.
51 scp $SCP_OPTS $DEPLOY_DIR/setup-clamav.sh $DEPLOY_DIR/setup-yara-rules.sh $SERVER:$REMOTE_DIR/deploy/
52 ssh $SSH_OPTS $SERVER "chmod +x $REMOTE_DIR/deploy/setup-firewall.sh $REMOTE_DIR/deploy/setup-git-ssh.sh $REMOTE_DIR/deploy/setup-ssh-keys.sh $REMOTE_DIR/deploy/setup-clamav.sh $REMOTE_DIR/deploy/setup-yara-rules.sh 2>/dev/null || true"
53
54 # Minify CSS for production (restore source on exit)
55 echo "[config] Minifying CSS..."
56 cp static/style.css static/style.css.src
57 restore_css() { [ -f static/style.css.src ] && mv static/style.css.src static/style.css; }
58 trap restore_css EXIT
59 npx --yes clean-css-cli -o static/style.css static/style.css.src
60 echo "[config] CSS: $(wc -c < static/style.css.src | tr -d ' ')B -> $(wc -c < static/style.css | tr -d ' ')B"
61
62 # Static assets (CSS, JS, fonts, images)
63 echo "[config] Uploading static assets..."
64 rsync -az --delete static/ $SERVER:$REMOTE_DIR/static/
65
66 # Restore unminified CSS
67 restore_css
68 trap - EXIT
69
70 # Documentation (public markdown files + UI examples)
71 echo "[config] Uploading documentation..."
72 rsync -az --delete site-docs/public/ $SERVER:$REMOTE_DIR/docs/public/
73 rsync -az --delete site-docs/examples/ $SERVER:$REMOTE_DIR/docs/examples/
74
75 # Business assumptions (source-of-truth for substituted figures in docs)
76 # Lives in the private docs store outside the repo (moved 2026-05-20).
77 rsync -az docs/business/assumptions.toml $SERVER:$REMOTE_DIR/docs/assumptions.toml
78
79 # Rustdoc (API reference for library crates)
80 echo "[config] Generating rustdoc..."
81 "$DEPLOY_DIR/generate-rustdoc.sh"
82 echo "[config] Uploading rustdoc..."
83 rsync -az --delete rustdoc-out/ $SERVER:$REMOTE_DIR/rustdoc/
84
85 # Reload systemd and restart Caddy
86 ssh $SSH_OPTS $SERVER "systemctl daemon-reload && systemctl restart caddy"
87 echo "[config] Done"
88 }
89
90 build_binary() {
91 echo "[build] Cross-compiling for $TARGET..."
92 ulimit -n 65536 2>/dev/null || true
93 cargo zigbuild --release --target $TARGET
94 echo "[build] Done: target/$TARGET/release/$BINARY_NAME"
95 }
96
97 upload_binary() {
98 echo "[upload] Stopping service and uploading binary..."
99 ssh $SSH_OPTS $SERVER "systemctl stop makenotwork || true"
100 scp $SCP_OPTS target/$TARGET/release/$BINARY_NAME $SERVER:$REMOTE_DIR/$BINARY_NAME
101 ssh $SSH_OPTS $SERVER "chmod +x $REMOTE_DIR/$BINARY_NAME"
102 # Also upload mnw-admin binary (used for SSH key management)
103 if [ -f "target/$TARGET/release/mnw-admin" ]; then
104 scp $SCP_OPTS target/$TARGET/release/mnw-admin $SERVER:$REMOTE_DIR/mnw-admin
105 ssh $SSH_OPTS $SERVER "chmod +x $REMOTE_DIR/mnw-admin"
106 echo "[upload] mnw-admin binary uploaded"
107 fi
108 echo "[upload] Done"
109 }
110
111 send_restart_warning() {
112 echo "[warning] Sending 30s restart warning to users..."
113 local token
114 token=$(ssh $SSH_OPTS $SERVER "grep '^CLI_SERVICE_TOKEN=' $REMOTE_DIR/.env 2>/dev/null | cut -d= -f2-" | tr -d '\r\n')
115 if [ -z "$token" ]; then
116 echo "[warning] CLI_SERVICE_TOKEN not found in .env, skipping warning"
117 return 0
118 fi
119 local status
120 status=$(ssh $SSH_OPTS $SERVER "curl -s -o /dev/null -w '%{http_code}' -X POST http://127.0.0.1:3000/api/internal/restart-warning -H 'Authorization: Bearer $token' -H 'Content-Type: application/json' -d '{\"seconds\": 30}'")
121 if [ "$status" = "204" ]; then
122 echo "[warning] Restart warning sent, waiting 30s..."
123 sleep 30
124 else
125 echo "[warning] Warning request returned HTTP $status, continuing without delay"
126 fi
127 }
128
129 restart_app() {
130 echo "[restart] Restarting makenotwork..."
131 ssh $SSH_OPTS $SERVER "systemctl restart makenotwork"
132 sleep 1
133 echo ""
134 ssh $SSH_OPTS $SERVER "systemctl status makenotwork --no-pager"
135 echo ""
136 echo "[restart] Verifying app responds..."
137 ssh $SSH_OPTS $SERVER "curl -s -o /dev/null -w 'HTTP %{http_code}\n' http://127.0.0.1:3000"
138 }
139
140 case "${1:-full}" in
141 --quick)
142 echo "=== Quick Deploy ==="
143 build_binary
144 send_restart_warning
145 upload_binary
146 restart_app
147 ;;
148 --config)
149 echo "=== Config Deploy ==="
150 upload_config
151 ;;
152 full|"")
153 echo "=== Full Deploy ==="
154 build_binary
155 upload_config
156 send_restart_warning
157 upload_binary
158 restart_app
159 ;;
160 *)
161 echo "Usage: $0 [--quick|--config]"
162 exit 1
163 ;;
164 esac
165
166 echo ""
167 echo "=== Deploy Complete ==="
168