Created
May 10, 2026 12:51
-
-
Save koliadych/73b64a3bc8295bad755903b94ba03b13 to your computer and use it in GitHub Desktop.
fintechner recovery: finish bootstrap on EC2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # fintechner — finish the EC2 bootstrap that user-data couldn't complete | |
| # (Caddy is not in AL2023's default dnf repos; install from official binary). | |
| # | |
| # Run on the EC2 via: aws ssm start-session ... then paste the curl below. | |
| # Idempotent — safe to re-run. | |
| set -euo pipefail | |
| REGION="ap-northeast-1" | |
| EMAIL="koliadych@gmail.com" | |
| HOSTNAME="13-193-136-150.sslip.io" | |
| CADDY_VERSION="2.10.2" | |
| echo "=== 1. Install Caddy from official binary ===" | |
| if [ ! -x /usr/bin/caddy ]; then | |
| curl -fsSL "https://github.com/caddyserver/caddy/releases/download/v${CADDY_VERSION}/caddy_${CADDY_VERSION}_linux_arm64.tar.gz" \ | |
| -o /tmp/caddy.tar.gz | |
| sudo tar -xzf /tmp/caddy.tar.gz -C /usr/bin/ caddy | |
| sudo chmod +x /usr/bin/caddy | |
| rm /tmp/caddy.tar.gz | |
| fi | |
| # System user + dirs. | |
| getent group caddy >/dev/null || sudo groupadd --system caddy | |
| getent passwd caddy >/dev/null || sudo useradd --system --gid caddy --no-create-home \ | |
| --home-dir /var/lib/caddy --shell /usr/sbin/nologin --comment "Caddy" caddy | |
| sudo mkdir -p /etc/caddy /var/lib/caddy /var/log/caddy | |
| sudo chown -R caddy:caddy /var/lib/caddy /var/log/caddy | |
| echo "=== 2. Write Caddyfile ===" | |
| sudo tee /etc/caddy/Caddyfile >/dev/null <<EOF | |
| { | |
| email ${EMAIL} | |
| } | |
| ${HOSTNAME} { | |
| reverse_proxy localhost:3000 | |
| handle_path /api/* { | |
| reverse_proxy localhost:8080 | |
| } | |
| handle_path /ws { | |
| reverse_proxy localhost:8080 | |
| } | |
| encode gzip zstd | |
| log { | |
| output file /var/log/caddy/access.log | |
| } | |
| } | |
| EOF | |
| echo "=== 3. Caddy systemd unit ===" | |
| sudo tee /etc/systemd/system/caddy.service >/dev/null <<'UNIT' | |
| [Unit] | |
| Description=Caddy | |
| Documentation=https://caddyserver.com/docs/ | |
| After=network-online.target | |
| Wants=network-online.target | |
| [Service] | |
| User=caddy | |
| Group=caddy | |
| ExecStart=/usr/bin/caddy run --environ --config /etc/caddy/Caddyfile | |
| ExecReload=/usr/bin/caddy reload --config /etc/caddy/Caddyfile --force | |
| TimeoutStopSec=5s | |
| LimitNOFILE=1048576 | |
| LimitNPROC=512 | |
| PrivateTmp=true | |
| ProtectSystem=full | |
| AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE | |
| [Install] | |
| WantedBy=multi-user.target | |
| UNIT | |
| sudo systemctl daemon-reload | |
| sudo systemctl enable --now caddy | |
| echo "=== 4. Pull DB password and start TimescaleDB ===" | |
| DB_PWD=$(aws --region "$REGION" secretsmanager get-secret-value \ | |
| --secret-id fintechner/db-password --query SecretString --output text) | |
| sudo mkdir -p /var/lib/timescale | |
| if ! sudo docker ps -a --format '{{.Names}}' | grep -q '^timescale$'; then | |
| sudo docker run -d --name timescale --restart unless-stopped \ | |
| -p 127.0.0.1:5432:5432 \ | |
| -e POSTGRES_USER=fintechner \ | |
| -e POSTGRES_PASSWORD="$DB_PWD" \ | |
| -e POSTGRES_DB=fintechner \ | |
| -v /var/lib/timescale:/var/lib/postgresql/data \ | |
| timescale/timescaledb:latest-pg16 | |
| elif ! sudo docker ps --format '{{.Names}}' | grep -q '^timescale$'; then | |
| sudo docker start timescale | |
| fi | |
| echo "=== 5. Connector + dashboard systemd units (binaries deployed later) ===" | |
| sudo mkdir -p /opt/fintechner/bin /opt/fintechner/dashboard /etc/fintechner | |
| sudo tee /etc/systemd/system/fintechner-connector.service >/dev/null <<'UNIT' | |
| [Unit] | |
| Description=fintechner connector | |
| After=network-online.target docker.service | |
| Requires=docker.service | |
| ConditionPathExists=/opt/fintechner/bin/connector | |
| [Service] | |
| EnvironmentFile=/etc/fintechner/connector.env | |
| ExecStart=/opt/fintechner/bin/connector | |
| Restart=always | |
| RestartSec=5s | |
| User=ec2-user | |
| [Install] | |
| WantedBy=multi-user.target | |
| UNIT | |
| sudo tee /etc/systemd/system/fintechner-dashboard.service >/dev/null <<'UNIT' | |
| [Unit] | |
| Description=fintechner dashboard | |
| After=network-online.target | |
| ConditionPathExists=/opt/fintechner/dashboard/server.js | |
| [Service] | |
| WorkingDirectory=/opt/fintechner/dashboard | |
| EnvironmentFile=/etc/fintechner/dashboard.env | |
| ExecStart=/usr/bin/node server.js | |
| Restart=always | |
| RestartSec=5s | |
| User=ec2-user | |
| Environment=PORT=3000 | |
| [Install] | |
| WantedBy=multi-user.target | |
| UNIT | |
| sudo systemctl daemon-reload | |
| echo " systemd units written. Connector and dashboard will start once binaries land in /opt/fintechner/." | |
| echo | |
| echo "============================================================" | |
| echo " RECOVERY COMPLETE" | |
| echo "============================================================" | |
| sudo systemctl is-active caddy && echo " caddy: active" | |
| sudo docker ps --format ' timescale: {{.Status}}' | grep timescale || echo " timescale: NOT running" | |
| echo | |
| echo "Test the URL: https://${HOSTNAME}" | |
| echo "Caddy will fetch a Lets Encrypt cert on first request (~30 sec)." |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment