Skip to content

Instantly share code, notes, and snippets.

@koliadych
Created May 10, 2026 12:51
Show Gist options
  • Select an option

  • Save koliadych/73b64a3bc8295bad755903b94ba03b13 to your computer and use it in GitHub Desktop.

Select an option

Save koliadych/73b64a3bc8295bad755903b94ba03b13 to your computer and use it in GitHub Desktop.
fintechner recovery: finish bootstrap on EC2
#!/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