diff --git a/roles/podman_forgejo/templates/forgejo.container b/roles/podman_forgejo/templates/forgejo.container index a213a64..9d8e00c 100644 --- a/roles/podman_forgejo/templates/forgejo.container +++ b/roles/podman_forgejo/templates/forgejo.container @@ -11,23 +11,8 @@ Environment=FORGEJO__database__HOST=mariadb:3306 Environment=FORGEJO__database__NAME={{ podman_forgejo_mariadb_database }} Environment=FORGEJO__database__USER={{ podman_forgejo_mariadb_user }} Environment=FORGEJO__database__PASSWD={{ podman_forgejo_mariadb_password }} -Environment=FORGEJO__email_0X2E_incoming__ENABLED=true -Environment=FORGEJO__email_0X2E_incoming__REPLY_TO_ADDRESS={{ podman_forgejo_reply_to }} -Environment=FORGEJO__email_0X2E_incoming__HOST={{ podman_forgejo_imap_hostname }} -Environment=FORGEJO__email_0X2E_incoming__PORT=993 -Environment=FORGEJO__email_0X2E_incoming__USERNAME={{ podman_forgejo_imap_username }} -Environment=FORGEJO__email_0X2E_incoming__PASSWORD={{ podman_forgejo_imap_password }} -Environment=FORGEJO__email_0X2E_incoming__USE_TLS=true Environment=FORGEJO__oauth2_client__ENABLE_AUTO_REGISTRATION=true Environment=FORGEJO__server__LANDING_PAGE=/explore/repos -Environment=FORGEJO__service__ENABLE_NOTIFY_MAIL=true -Environment=FORGEJO__mailer__ENABLED=true -Environment=FORGEJO__mailer__PROTOCOL=smtps -Environment=FORGEJO__mailer__SMTP_ADDR={{ podman_forgejo_smtp_hostname }} -Environment=FORGEJO__mailer__SMTP_PORT=465 -Environment=FORGEJO__mailer__USER={{ podman_forgejo_smtp_username }} -Environment=FORGEJO__mailer__PASSWD={{ podman_forgejo_smtp_password }} -Environment=FORGEJO__mailer__FROM={{ podman_forgejo_smtp_from }} Image=codeberg.org/forgejo/forgejo:11 Network=frontend.network Network=forgejo.network diff --git a/roles/podman_host/defaults/main.yml b/roles/podman_host/defaults/main.yml new file mode 100644 index 0000000..558c897 --- /dev/null +++ b/roles/podman_host/defaults/main.yml @@ -0,0 +1,3 @@ +--- +podman_host_minimum_unpriv_port: "22" +podman_host_rootless_users: ["podman"] diff --git a/roles/podman_host/tasks/main.yml b/roles/podman_host/tasks/main.yml new file mode 100644 index 0000000..36e5ca9 --- /dev/null +++ b/roles/podman_host/tasks/main.yml @@ -0,0 +1,69 @@ +--- +- name: set unprivileged port minimum + ansible.posix.sysctl: + name: net.ipv4.ip_unprivileged_port_start + value: "{{ podman_host_minimum_unpriv_port }}" + sysctl_set: true + sysctl_file: /etc/sysctl.d/zzz-podman-unpriv-port.conf + reload: true + become: true + +- name: create users for rootless podman + ansible.builtin.user: + name: "{{ item }}" + become: true + with_items: "{{ podman_host_rootless_users }}" + +- name: set XDG_RUNTIME_DIR in .profile for rootless users + ansible.builtin.lineinfile: + path: "/home/{{ item }}/.bashrc" + line: "export XDG_RUNTIME_DIR=/run/user/$(id -u)" + create: false + become: true + become_user: "{{ item }}" + with_items: "{{ podman_host_rootless_users }}" + +- name: enable linger for rootless users + ansible.builtin.command: + argv: + - /usr/bin/loginctl + - enable-linger + - "{{ item }}" + creates: "/var/lib/systemd/linger/{{ item }}" + become: true + with_items: "{{ podman_host_rootless_users }}" + +- name: create /etc/subuid and /etc/subgid + ansible.builtin.template: + dest: "/etc/{{ item }}" + src: subXid.j2 + with_items: + - subuid + - subgid + become: true + +- name: install podman + ansible.builtin.apt: + pkg: podman + state: latest + become: true + +- name: create quadlets directory + ansible.builtin.file: + path: "/home/{{ item }}/.config/containers/systemd" + state: directory + owner: "{{ item }}" + group: "{{ item }}" + mode: "0700" + with_items: "{{ podman_host_rootless_users }}" + become: true + +- name: enable podman auto update timer for rootless users + ansible.builtin.systemd_service: + name: podman-auto-update.timer + scope: user + state: started + enabled: true + become: true + become_user: "{{ item }}" + with_items: "{{ podman_host_rootless_users }}" diff --git a/roles/podman_host/templates/subXid.j2 b/roles/podman_host/templates/subXid.j2 new file mode 100644 index 0000000..a8022c6 --- /dev/null +++ b/roles/podman_host/templates/subXid.j2 @@ -0,0 +1,4 @@ +# {{ ansible_managed }} +{% for username in podman_host_rootless_users %} +{{ username }}:{{ 100000 + ((loop.index - 1) * 65536) }}:65536 +{% endfor %} diff --git a/roles/podman_nginx/defaults/main.yml b/roles/podman_nginx/defaults/main.yml new file mode 100644 index 0000000..5d6b76e --- /dev/null +++ b/roles/podman_nginx/defaults/main.yml @@ -0,0 +1,6 @@ +--- +podman_nginx_additional_hostnames: [] +podman_nginx_certbot_testing: false +# podman_nginx_frontend_network: +podman_nginx_podman_rootless_user: nginx +# podman_nginx_primary_hostname: \ No newline at end of file diff --git a/roles/podman_nginx/handlers/main.yml b/roles/podman_nginx/handlers/main.yml new file mode 100644 index 0000000..f1b17d9 --- /dev/null +++ b/roles/podman_nginx/handlers/main.yml @@ -0,0 +1,18 @@ +--- +- name: restart certbot-renew + ansible.builtin.systemd_service: + name: certbot-renew + state: started + scope: user + daemon_reload: true + become: true + become_user: "{{ podman_nginx_podman_rootless_user }}" + +- name: restart nginx + ansible.builtin.systemd_service: + name: nginx + state: restarted + scope: user + daemon_reload: true + become: true + become_user: "{{ podman_nginx_podman_rootless_user }}" diff --git a/roles/podman_nginx/tasks/main.yml b/roles/podman_nginx/tasks/main.yml new file mode 100644 index 0000000..7d3f3c8 --- /dev/null +++ b/roles/podman_nginx/tasks/main.yml @@ -0,0 +1,110 @@ +--- +- name: create service configuration directories + ansible.builtin.file: + path: "/home/{{ podman_nginx_podman_rootless_user }}/{{ item }}" + state: directory + owner: "{{ podman_nginx_podman_rootless_user }}" + group: "{{ podman_nginx_podman_rootless_user }}" + mode: "0755" + become: true + with_items: + - .config/systemd/user + - certbot/conf + - certbot/www + - nginx + +- name: install podman quadlet for rootless podman user + ansible.builtin.template: + src: "{{ item }}" + dest: "/home/{{ podman_nginx_podman_rootless_user }}/.config/containers/systemd/{{ item }}" + owner: "{{ podman_nginx_podman_rootless_user }}" + mode: "0400" + with_items: + - certbot-renew.container + - nginx.container + notify: + - "restart {{ item | split('.') | first }}" + become: true + +- name: install certbot renewal timer for rootless podman user + ansible.builtin.template: + src: "certbot-renew.timer" + dest: "/home/{{ podman_nginx_podman_rootless_user }}/.config/systemd/user/certbot-renew.timer" + owner: "{{ podman_nginx_podman_rootless_user }}" + mode: "0400" + become: true + +- name: verify quadlets are correctly defined + ansible.builtin.command: /usr/libexec/podman/quadlet -dryrun -user + register: podman_nginx_quadlet_result + ignore_errors: true + changed_when: false + become: true + become_user: "{{ podman_nginx_podman_rootless_user }}" + +- name: check if certificate exists + stat: + path: "/home/{{ podman_nginx_podman_rootless_user }}/certbot/conf/live/{{ podman_nginx_primary_hostname }}/fullchain.pem" + register: podman_nginx_cert_stat + become: yes + become_user: "{{ podman_nginx_podman_rootless_user }}" + +- name: create temporary nginx configuration (no https) + ansible.builtin.template: + src: nginx.conf + dest: "/home/{{ podman_nginx_podman_rootless_user }}/nginx/nginx.conf" + owner: "{{ podman_nginx_podman_rootless_user }}" + group: "{{ podman_nginx_podman_rootless_user }}" + mode: "0644" + become: true + when: podman_nginx_cert_stat.stat.exists == false + +- name: start nginx + ansible.builtin.systemd_service: + name: nginx + state: started + scope: user + daemon_reload: true + become: true + become_user: "{{ podman_nginx_podman_rootless_user }}" + +- name: run certbot container to create certificate + ansible.builtin.command: + cmd: > + podman run --name certbot-generate + --rm + --volume /home/{{ podman_nginx_podman_rootless_user }}/certbot/www:/var/www/certbot:rw + --volume /home/{{ podman_nginx_podman_rootless_user }}/certbot/conf:/etc/letsencrypt:rw + docker.io/certbot/certbot:latest + certonly + --register-unsafely-without-email + --agree-tos + --webroot + --webroot-path /var/www/certbot/ + -d "{{ podman_nginx_primary_hostname }}" + {% for hostname in podman_nginx_additional_hostnames %} -d "{{ hostname }}"{% endfor %} + {% if podman_nginx_certbot_testing %} --test-cert{% endif %} + when: podman_nginx_cert_stat.stat.exists == false + become: yes + become_user: "{{ podman_nginx_podman_rootless_user }}" + +- name: check if certificate exists + stat: + path: "/home/{{ podman_nginx_podman_rootless_user }}/certbot/conf/live/{{ podman_nginx_primary_hostname }}/fullchain.pem" + register: podman_nginx_cert_stat + become: yes + become_user: "{{ podman_nginx_podman_rootless_user }}" + +- name: ensure certificate exists now + ansible.builtin.assert: + that: + - podman_nginx_cert_stat.stat.exists + fail_msg: "Failed to get a Lets Encrypt certificate." + +- name: start certbot renewal timer + ansible.builtin.systemd_service: + name: "certbot-renew.timer" + state: started + scope: user + become: true + become_user: "{{ podman_nginx_podman_rootless_user }}" diff --git a/roles/podman_nginx/templates/certbot-renew.container b/roles/podman_nginx/templates/certbot-renew.container new file mode 100644 index 0000000..7d28fd4 --- /dev/null +++ b/roles/podman_nginx/templates/certbot-renew.container @@ -0,0 +1,13 @@ +[Unit] +Description=Run certbot renew + +[Container] +AutoUpdate=registry +ContainerName=certbot-renew +Exec=renew +Image=docker.io/certbot/certbot:latest +Volume=/home/{{ podman_nginx_podman_rootless_user }}/certbot/www:/var/www/certbot +Volume=/home/{{ podman_nginx_podman_rootless_user }}/certbot/conf:/etc/letsencrypt + +[Service] +Restart=no diff --git a/roles/podman_nginx/templates/certbot-renew.timer b/roles/podman_nginx/templates/certbot-renew.timer new file mode 100644 index 0000000..65f32c1 --- /dev/null +++ b/roles/podman_nginx/templates/certbot-renew.timer @@ -0,0 +1,9 @@ +[Unit] +Description=Timer for certbot renewals + +[Timer] +OnCalendar=daily +Persistent=true + +[Install] +WantedBy=timers.target diff --git a/roles/podman_nginx/templates/nginx.conf b/roles/podman_nginx/templates/nginx.conf new file mode 100644 index 0000000..aea3186 --- /dev/null +++ b/roles/podman_nginx/templates/nginx.conf @@ -0,0 +1,17 @@ +# {{ ansible_managed }} + +server { + listen 80; + listen [::]:80; + + server_name {{ podman_nginx_primary_hostname }}; + server_tokens off; + + location /.well-known/acme-challenge/ { + root /var/www/certbot; + } + + location / { + return 301 https://{{ podman_nginx_primary_hostname }}$request_uri; + } +} diff --git a/roles/podman_nginx/templates/nginx.container b/roles/podman_nginx/templates/nginx.container new file mode 100644 index 0000000..fb8cafe --- /dev/null +++ b/roles/podman_nginx/templates/nginx.container @@ -0,0 +1,16 @@ +[Container] +ContainerName=nginx +Image=docker.io/nginx:latest +{% if podman_nginx_frontend_network is defined %}Network={{ podman_nginx_frontend_network }}.network{% endif +%} +PublishPort=80:80 +PublishPort=443:443 +Volume=/home/{{ podman_nginx_podman_rootless_user }}/certbot/www:/var/www/certbot/:ro +Volume=/home/{{ podman_nginx_podman_rootless_user }}/certbot/conf/:/etc/letsencrypt/:ro +Volume=/home/{{ podman_nginx_podman_rootless_user }}/nginx:/etc/nginx/conf.d/:ro + +[Service] +RuntimeMaxSec=604800 +Restart=always + +[Install] +WantedBy=default.target diff --git a/roles/vps/tasks/main.yml b/roles/vps/tasks/main.yml new file mode 100644 index 0000000..759a183 --- /dev/null +++ b/roles/vps/tasks/main.yml @@ -0,0 +1,35 @@ +--- +# https://support.solusvm.com/hc/en-us/articles/21334950006807-How-to-install-Guest-Tools-manually-inside-a-VM-in-SolusVM-2 + +- name: install required packages + apt: + pkg: + - qemu-guest-agent + - cloud-init + - tuned + state: latest + cache_valid_time: 3600 + become: true + when: ansible_distribution == 'Debian' + +- name: install required packages + dnf: + name: + - qemu-guest-agent + - cloud-init + - tuned + state: latest + update_cache: true + become: true + when: ansible_distribution == 'AlmaLinux' + +- name: check tuned profile + command: tuned-adm active + register: vps_tuned_profile + become: true + changed_when: false + +- name: start tuned profile + shell: tuned-adm profile virtual-guest + become: true + when: "'virtual-guest' not in vps_tuned_profile.stdout"