aegis402/deploy/cloud-init.yaml

157 lines
4.5 KiB
YAML

#cloud-config
# Aegis402 — VPS bootstrap (SporeStack / Hetzner / any cloud-init compatible host)
# Hardened, no telemetry, no third-party agent.
# Replace AEGIS402_PUBLIC_URL and AEGIS402_WALLET_PASS placeholders before launch.
hostname: aegis402
preserve_hostname: false
manage_etc_hosts: true
timezone: UTC
users:
- name: aegis
sudo: ALL=(ALL) NOPASSWD:ALL
shell: /bin/bash
lock_passwd: true
ssh_authorized_keys:
- REPLACE_WITH_YOUR_SSH_PUBKEY
package_update: true
package_upgrade: true
packages:
- python3.12
- python3.12-venv
- python3-pip
- git
- ufw
- fail2ban
- sqlite3
- nginx
- certbot
- python3-certbot-nginx
- unattended-upgrades
write_files:
- path: /etc/aegis402.env
permissions: '0600'
owner: aegis:aegis
content: |
AEGIS402_X402_ENABLED=1
AEGIS402_X402_STRICT=1
AEGIS402_X402_FACILITATOR=https://x402.org/facilitator
AEGIS402_PUBLIC_URL=https://REPLACE_DOMAIN/
AEGIS402_WALLET_PASS=REPLACE_32CHAR_RANDOM_PASS_FROM_LOCAL
- path: /etc/systemd/system/aegis402.service
content: |
[Unit]
Description=Aegis402 API
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=aegis
Group=aegis
WorkingDirectory=/home/aegis/aegis402
EnvironmentFile=/etc/aegis402.env
ExecStart=/home/aegis/aegis402/venv/bin/uvicorn src.server:app \
--host 127.0.0.1 --port 8743 --workers 2 --log-level info
Restart=always
RestartSec=5
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=read-only
ReadWritePaths=/home/aegis/aegis402/data
LimitNOFILE=4096
[Install]
WantedBy=multi-user.target
- path: /etc/systemd/system/aegis402-ingest.service
content: |
[Unit]
Description=Aegis402 ingest GHSA + KEV
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
User=aegis
Group=aegis
WorkingDirectory=/home/aegis/aegis402
EnvironmentFile=/etc/aegis402.env
ExecStart=/home/aegis/aegis402/venv/bin/python -m src.ingest_ghsa
ExecStart=/home/aegis/aegis402/venv/bin/python -m src.ingest_kev
Nice=10
TimeoutStartSec=900
- path: /etc/systemd/system/aegis402-ingest.timer
content: |
[Unit]
Description=Aegis402 ingest every 60 min
Requires=aegis402-ingest.service
[Timer]
OnBootSec=3min
OnUnitActiveSec=60min
RandomizedDelaySec=120
Persistent=true
Unit=aegis402-ingest.service
[Install]
WantedBy=timers.target
- path: /etc/nginx/sites-available/aegis402
content: |
server {
listen 80 default_server;
server_name _;
location / {
proxy_pass http://127.0.0.1:8743;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_read_timeout 30s;
client_max_body_size 256k;
}
}
runcmd:
# Firewall
- ufw default deny incoming
- ufw default allow outgoing
- ufw allow 22/tcp
- ufw allow 80/tcp
- ufw allow 443/tcp
- ufw --force enable
# Unattended security upgrades
- dpkg-reconfigure -f noninteractive unattended-upgrades
# App install
- sudo -u aegis git clone https://REPLACE_GIT_REMOTE /home/aegis/aegis402
- sudo -u aegis python3.12 -m venv /home/aegis/aegis402/venv
- sudo -u aegis /home/aegis/aegis402/venv/bin/pip install --upgrade pip
- sudo -u aegis /home/aegis/aegis402/venv/bin/pip install -r /home/aegis/aegis402/requirements.txt
- sudo -u aegis mkdir -p /home/aegis/aegis402/data
- sudo -u aegis /home/aegis/aegis402/venv/bin/python -c "from src.db import init_db; init_db()"
- sudo -u aegis /home/aegis/aegis402/venv/bin/python -m src.wallet
- sudo -u aegis /home/aegis/aegis402/venv/bin/python -m src.ingest_ghsa
- sudo -u aegis /home/aegis/aegis402/venv/bin/python -m src.ingest_kev
# Nginx + TLS
- ln -s /etc/nginx/sites-available/aegis402 /etc/nginx/sites-enabled/aegis402
- rm -f /etc/nginx/sites-enabled/default
- nginx -t && systemctl restart nginx
# Replace REPLACE_DOMAIN below before launch:
# - certbot --nginx -d REPLACE_DOMAIN --non-interactive --agree-tos -m REPLACE_EMAIL --redirect
# Services
- systemctl daemon-reload
- systemctl enable --now aegis402.service
- systemctl enable --now aegis402-ingest.timer
final_message: "Aegis402 bootstrap complete. Set DNS to this IP, then run certbot."