commit 2e4c47fa076b9de7cb6672f0adb79ebab6e08c76 Author: Emi Matchu Date: Wed Feb 28 13:15:31 2024 -0800 Initial commit: It's working! :3 diff --git a/ansible.cfg b/ansible.cfg new file mode 100644 index 0000000..2271ddb --- /dev/null +++ b/ansible.cfg @@ -0,0 +1,5 @@ +[defaults] +inventory = inventory.cfg + +[privilege_escalation] +become_ask_pass = True diff --git a/files/.gitignore b/files/.gitignore new file mode 100644 index 0000000..261fc89 --- /dev/null +++ b/files/.gitignore @@ -0,0 +1 @@ +/glitchtip-conf.env diff --git a/files/docker-compose.yml b/files/docker-compose.yml new file mode 100644 index 0000000..70be678 --- /dev/null +++ b/files/docker-compose.yml @@ -0,0 +1,58 @@ +version: "3.8" + +# NOTE: We override many of these in our secret `glitchtip-conf.env` file, +# which we provide as the `env_file` to some of the services below! +x-environment: &default-environment + DATABASE_URL: postgres://postgres:postgres@postgres:5432/postgres + # SECRET_KEY: change_me # best to run openssl rand -hex 32 + PORT: 8000 + # EMAIL_URL: consolemail:// # Example smtp://email:password@smtp_url:port https://glitchtip.com/documentation/install#configuration + # GLITCHTIP_DOMAIN: https://app.glitchtip.com # Change this to your domain + # DEFAULT_FROM_EMAIL: email@glitchtip.com # Change this to your email + CELERY_WORKER_AUTOSCALE: "1,3" # Scale between 1 and 3 to prevent excessive memory usage. Change it or remove to set it to the number of cpu cores. + CELERY_WORKER_MAX_TASKS_PER_CHILD: "10000" + +x-depends_on: &default-depends_on + - postgres + - redis + +services: + postgres: + image: postgres:15 + environment: + POSTGRES_HOST_AUTH_METHOD: "trust" # Consider removing this and setting a password + restart: unless-stopped + volumes: + - pg-data:/var/lib/postgresql/data + redis: + image: redis + restart: unless-stopped + web: + image: glitchtip/glitchtip + depends_on: *default-depends_on + ports: + - "8000:8000" + environment: *default-environment + restart: unless-stopped + volumes: + - uploads:/code/uploads + env_file: glitchtip-conf.env + worker: + image: glitchtip/glitchtip + command: ./bin/run-celery-with-beat.sh + depends_on: *default-depends_on + environment: *default-environment + restart: unless-stopped + volumes: + - uploads:/code/uploads + env_file: glitchtip-conf.env + migrate: + image: glitchtip/glitchtip + depends_on: *default-depends_on + command: "./manage.py migrate" + environment: *default-environment + env_file: glitchtip-conf.env + +volumes: + pg-data: + uploads: diff --git a/files/docker.gpg b/files/docker.gpg new file mode 100755 index 0000000..e5dc8cf Binary files /dev/null and b/files/docker.gpg differ diff --git a/files/glitchtip.service b/files/glitchtip.service new file mode 100644 index 0000000..dfd2e94 --- /dev/null +++ b/files/glitchtip.service @@ -0,0 +1,31 @@ +[Unit] +Description=GlitchTip server (via Docker) +Requires=docker.service +After=docker.service + +[Service] +User=glitchtip +Restart=always +WorkingDirectory=/srv/glitchtip + +# If there's already a container instance, shut it down before starting. +ExecStartPre=/usr/bin/docker compose down +ExecStart=/usr/bin/docker compose up +ExecStop=/usr/bin/docker compose down + +; Some security directives, adapted from Akkoma's service file, they seem like sensible defaults! +; Use private /tmp and /var/tmp folders inside a new file system namespace, which are discarded after the process stops. +PrivateTmp=true +; The /home, /root, and /run/user folders can not be accessed by this service anymore. If your Akkoma user has its home folder in one of the restricted places, or use one of these folders as its working directory, you have to set this to false. +ProtectHome=true +; Mount /usr, /boot, and /etc as read-only for processes invoked by this service. +ProtectSystem=full +; Sets up a new /dev mount for the process and only adds API pseudo devices like /dev/null, /dev/zero or /dev/random but not physical devices. +PrivateDevices=true +; Ensures that the service process and all its children can never gain new privileges through execve(). +NoNewPrivileges=true +; Drops the sysadmin capability from the daemon. +CapabilityBoundingSet=~CAP_SYS_ADMIN + +[Install] +WantedBy=multi-user.target diff --git a/inventory.cfg b/inventory.cfg new file mode 100644 index 0000000..79a4a86 --- /dev/null +++ b/inventory.cfg @@ -0,0 +1,2 @@ +[health] +health.openneo.net diff --git a/setup-glitchtip.yml b/setup-glitchtip.yml new file mode 100644 index 0000000..7ad80e3 --- /dev/null +++ b/setup-glitchtip.yml @@ -0,0 +1,89 @@ +--- +- name: Install and configure Glitchtip + hosts: health + become: yes + become_user: root + tasks: + - name: Add current user to the Docker group + user: + name: "{{ lookup('env', 'USER') }}" + groups: + - docker + append: yes + + - name: Set DPKG architecture as a variable + set_fact: + dpkg_arch: "{{ 'amd64' if ansible_architecture == 'x86_64' else ansible_architecture }}" + + # From https://download.docker.com/linux/debian/gpg, then dearmored. + - name: Upload Docker's GPG key + copy: + src: files/docker.gpg + dest: /etc/apt/keyrings/docker.gpg + + - name: Add Docker's apt repository + apt_repository: + repo: "deb [arch={{ dpkg_arch }} signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian {{ ansible_distribution_release }} stable" + + - name: Update the apt cache + apt: + update_cache: yes + + - name: Install Docker + apt: + name: docker-ce + + - name: Create glitchtip user + user: + name: glitchtip + groups: + - docker + home: /srv/glitchtip + create_home: no + comment: Glitchtip service user + + - name: Create /srv/glitchtip folder + file: + path: /srv/glitchtip + owner: glitchtip + group: glitchtip + mode: "0700" + state: directory + + - name: Copy docker-compose.yml to /srv/glitchtip + copy: + src: files/docker-compose.yml + dest: /srv/glitchtip/docker-compose.yml + notify: + - Restart glitchtip + + - name: Copy glitchtip-conf.env to /srv/glitchtip + copy: + src: files/glitchtip-conf.env + dest: /srv/glitchtip/glitchtip-conf.env + notify: + - Restart glitchtip + + - name: Create service file for glitchtip + copy: + src: files/glitchtip.service + dest: /etc/systemd/system/glitchtip.service + notify: + - Reload systemctl + - Restart glitchtip + + - name: Enable the glitchtip service + systemd_service: + name: glitchtip + enabled: yes + state: started + + handlers: + - name: Reload systemctl + systemd_service: + daemon_reload: true + + - name: Restart glitchtip + systemd_service: + name: glitchtip + state: restarted diff --git a/setup-nginx.yml b/setup-nginx.yml new file mode 100644 index 0000000..cd53fae --- /dev/null +++ b/setup-nginx.yml @@ -0,0 +1,77 @@ +--- +- name: Install the nginx web server as our HTTPS reverse-proxy + hosts: health + become: yes + become_user: root + vars: + admin_email: emi@matchu.dev + tasks: + - name: Update the apt cache + apt: + update_cache: yes + + - name: Install nginx + apt: + name: nginx + + - name: Install certbot + apt: + name: + - certbot + - python3-certbot-nginx + + - name: Set up the SSL certificate for health.openneo.net + command: "certbot certonly --nginx -n --agree-tos --email {{ admin_email }} --domains health.openneo.net" + + - name: Add glitchtip config file to nginx + copy: + dest: /etc/nginx/sites-available/glitchtip.conf + content: | + server { + server_name health.openneo.net; + listen 80; + listen [::]:80; + if ($host = health.openneo.net) { + return 301 https://$host$request_uri; + } + } + + server { + server_name health.openneo.net; + listen 443; + listen [::]:443 ssl; + ssl_certificate /etc/letsencrypt/live/health.openneo.net/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/health.openneo.net/privkey.pem; + include /etc/letsencrypt/options-ssl-nginx.conf; + ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; + ssl_session_cache shared:SSL:10m; # https://superuser.com/q/1484466/14127 + + # From GlitchTip recommended config + client_max_body_size 40M; + + location / { + proxy_pass http://127.0.0.1:8000; + + # From GlitchTip recommended config + 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; + } + } + notify: + - Restart nginx + + - name: Enable glitchtip config file in nginx + file: + src: /etc/nginx/sites-available/glitchtip.conf + dest: /etc/nginx/sites-enabled/glitchtip.conf + state: link + notify: + - Restart nginx + + handlers: + - name: Restart nginx + systemd: + name: nginx + state: restarted diff --git a/setup-security.yml b/setup-security.yml new file mode 100644 index 0000000..549f7c8 --- /dev/null +++ b/setup-security.yml @@ -0,0 +1,94 @@ +--- +- name: Set up security defaults + hosts: health + become: yes + become_user: root + vars: + open_ports: + - ssh + - http + - https + tasks: + - name: Disable insecure SSH authentication methods + copy: + dest: /etc/ssh/sshd_config.d/disable-insecure-logins.conf + content: | + PermitRootLogin no + PasswordAuthentication no + PubkeyAuthentication yes + notify: Restart SSH + + - name: Update the apt cache + apt: + update_cache: yes + + - name: Install fail2ban firewall with default settings + apt: + name: fail2ban + + - name: Install ufw firewall + apt: + name: ufw + + - name: Configure ufw firewall to allow SSH connections on port 22 + community.general.ufw: + rule: allow + port: "{{ item }}" + loop: "{{ open_ports }}" + + - name: Configure ufw firewall to deny access to ChatGPT-User's IP range + community.general.ufw: + rule: deny + src: 23.98.142.176/28 + comment: ChatGPT-User (https://platform.openai.com/docs/plugins/bot) + + - name: Load GPTBot IP ranges + uri: + url: https://openai.com/gptbot.json + register: gptbot_info + + - name: Configure ufw firewall to deny access to each of GPTBot's IP ranges + community.general.ufw: + rule: deny + src: "{{ item }}" + comment: GPTBot (https://platform.openai.com/docs/gptbot) + loop: "{{ gptbot_info['json'] | + community.general.json_query('prefixes[*].ipv4Prefix') }}" + + - name: Enable ufw firewall with all other ports closed by default + community.general.ufw: + state: enabled + policy: deny + + - name: Install unattended-upgrades + apt: + name: unattended-upgrades + + - name: Enable unattended-upgrades to auto-upgrade our system + copy: + content: | + APT::Periodic::Update-Package-Lists "1"; + APT::Periodic::Unattended-Upgrade "1"; + dest: /etc/apt/apt.conf.d/20auto-upgrades + + - name: Configure unattended-upgrades to auto-reboot our server when necessary + lineinfile: + regex: ^(//\s*)?Unattended-Upgrade::Automatic-Reboot ".*";$ + line: Unattended-Upgrade::Automatic-Reboot "true"; + dest: /etc/apt/apt.conf.d/50unattended-upgrades + + - name: Configure the system timezone to be US Pacific time + community.general.timezone: + name: America/Los_Angeles + + - name: Configure unattended-upgrades to delay necessary reboots to 3am + lineinfile: + regex: ^(//\s*)?Unattended-Upgrade::Automatic-Reboot-Time ".*";$ + line: Unattended-Upgrade::Automatic-Reboot-Time "03:00"; + dest: /etc/apt/apt.conf.d/50unattended-upgrades + + handlers: + - name: Restart SSH + systemd_service: + name: ssh + state: restarted diff --git a/setup-users.yml b/setup-users.yml new file mode 100644 index 0000000..8a70fac --- /dev/null +++ b/setup-users.yml @@ -0,0 +1,31 @@ +--- +- name: Set up user accounts + hosts: health + become: yes + become_user: root + tasks: + - name: Create user account for matchu + user: + name: matchu + groups: + - sudo + shell: /bin/bash + comment: Emi Matchu + + - name: Create matchu's .ssh folder + file: + name: /home/matchu/.ssh + mode: "700" + owner: matchu + group: matchu + state: directory + + - name: Set up matchu's public SSH keys + copy: + dest: /home/matchu/.ssh/authorized_keys + mode: "600" + owner: matchu + group: matchu + content: | + ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIu5a+mp2KKSGkOGWQPrARCrsqJS4g2vK7TmRIbj/YBh Matchu's Desktop (Leviathan 2023) + ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKFwWryq6slOQqkrJ7HIig7BvEQVQeH19hFwb+9VpXgz Matchu's Laptop (Ebon Hawk)