#cloud-config
# Cloud-init configuration for {{ project_name }}
# Generated by Prism

package_update: true
package_upgrade: true

packages:
  - apt-transport-https
  - ca-certificates
  - curl
  - gnupg
  - lsb-release
  - ufw
  - fail2ban
  - logrotate
  - htop
  - vim
  - nginx
  - certbot
  - python3-certbot-nginx
  - postgresql-client-{{ postgres_version }}

users:
  - name: deploy
    groups: sudo
    shell: /bin/bash
    sudo: ['ALL=(ALL) NOPASSWD:ALL']
    ssh_authorized_keys:
      - ${ssh_public_key}

runcmd:
  # Copy SSH keys from root to deploy user (Hetzner adds keys to root)
  - mkdir -p /home/deploy/.ssh
  - cp /root/.ssh/authorized_keys /home/deploy/.ssh/
  - chown -R deploy:deploy /home/deploy/.ssh
  - chmod 700 /home/deploy/.ssh
  - chmod 600 /home/deploy/.ssh/authorized_keys

  # Docker installation
  - curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
  - echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" > /etc/apt/sources.list.d/docker.list
  - apt-get update
  - apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
  - systemctl enable docker
  - systemctl start docker

  # Add deploy user to docker group
  - usermod -aG docker deploy

  # Configure firewall
  - ufw default deny incoming
  - ufw default allow outgoing
  - ufw allow 22/tcp comment 'SSH'
  - ufw allow 80/tcp comment 'HTTP'
  - ufw allow 443/tcp comment 'HTTPS'
  - ufw --force enable

  # Configure fail2ban
  - systemctl enable fail2ban
  - systemctl start fail2ban

{% if enable_swap %}
  # Setup swap
  - fallocate -l {{ swap_size_mb }}M /swapfile
  - chmod 600 /swapfile
  - mkswap /swapfile
  - swapon /swapfile
  - echo '/swapfile none swap sw 0 0' >> /etc/fstab
  - sysctl vm.swappiness=10
  - echo 'vm.swappiness=10' >> /etc/sysctl.conf
{% endif %}

  # Create application directory
  - mkdir -p /opt/{{ project_name }}
  - chown deploy:deploy /opt/{{ project_name }}

  # Create data directory for PostgreSQL (will be mounted from volume)
  - mkdir -p /mnt/data/postgres
  - chown -R 999:999 /mnt/data/postgres

  # Create backup directory
  - mkdir -p /opt/{{ project_name }}/backups
  - chown deploy:deploy /opt/{{ project_name }}/backups

  # Setup log rotation for Docker
  - |
    cat > /etc/logrotate.d/docker-containers << 'EOF'
    /var/lib/docker/containers/*/*.log {
      rotate 7
      daily
      compress
      missingok
      delaycompress
      copytruncate
    }
    EOF

  # Configure Docker daemon
  - |
    cat > /etc/docker/daemon.json << 'EOF'
    {
      "log-driver": "json-file",
      "log-opts": {
        "max-size": "10m",
        "max-file": "3"
      },
      "storage-driver": "overlay2"
    }
    EOF
  - systemctl restart docker

  # Create systemd service for application
  - |
    cat > /etc/systemd/system/{{ project_name }}.service << 'EOF'
    [Unit]
    Description={{ project_name }} Application
    Requires=docker.service
    After=docker.service

    [Service]
    Type=oneshot
    RemainAfterExit=yes
    WorkingDirectory=/opt/{{ project_name }}
    ExecStart=/usr/bin/docker compose -f docker-compose.prod.yml up -d
    ExecStop=/usr/bin/docker compose -f docker-compose.prod.yml down
    User=deploy
    Group=deploy
    TimeoutStartSec=300

    [Install]
    WantedBy=multi-user.target
    EOF
  - systemctl daemon-reload
  - systemctl enable {{ project_name }}.service

  # Create nginx default config (will be replaced after certbot)
  - |
    cat > /etc/nginx/sites-available/{{ project_name }} << 'EOF'
    server {
        listen 80;
        server_name _;

        location /health {
            return 200 'OK';
            add_header Content-Type text/plain;
        }

        location /api {
            proxy_pass http://127.0.0.1:8000;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_read_timeout 300;
            proxy_connect_timeout 300;
        }

        location /graphql {
            proxy_pass http://127.0.0.1:8000;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            # WebSocket support for GraphQL subscriptions
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_read_timeout 86400;
        }

        location / {
            proxy_pass http://127.0.0.1:3000;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
    }
    EOF
  - ln -sf /etc/nginx/sites-available/{{ project_name }} /etc/nginx/sites-enabled/
  - rm -f /etc/nginx/sites-enabled/default
  - nginx -t && systemctl restart nginx

write_files:
  - path: /opt/{{ project_name }}/.env.example
    content: |
      # {{ project_name }} Environment Variables
      # Copy this file to .env and configure

      PROJECT_NAME={{ project_name }}
      ENVIRONMENT=production

      # Database
      DATABASE_URL=postgresql://{{ postgres_user }}:CHANGE_ME@db:5432/{{ postgres_db }}
      POSTGRES_USER={{ postgres_user }}
      POSTGRES_PASSWORD=CHANGE_ME
      POSTGRES_DB={{ postgres_db }}

      # Security
      SECRET_KEY=GENERATE_WITH_openssl_rand_hex_32

      # Docker
      IMAGE_TAG=latest
{% if use_redis %}

      # Redis
      REDIS_URL=redis://redis:6379/0
{% endif %}
    owner: deploy:deploy
    permissions: '0600'
