diff --git a/containers/drone-runner/files/drone-runner-gc.service b/containers/drone-runner/files/drone-runner-gc.service new file mode 100644 index 0000000..79d12bf --- /dev/null +++ b/containers/drone-runner/files/drone-runner-gc.service @@ -0,0 +1,8 @@ + +[Unit] +Description=Remove unused podman resources spawned by drone runner +Wants=drone-runner-gc.timer + +[Service] +Type=oneshot +ExecStart=/bin/podman system prune --filter label=io.drone=true --volumes -f diff --git a/containers/drone-runner/files/drone-runner-gc.timer b/containers/drone-runner/files/drone-runner-gc.timer new file mode 100644 index 0000000..a76cf90 --- /dev/null +++ b/containers/drone-runner/files/drone-runner-gc.timer @@ -0,0 +1,11 @@ +[Unit] +Description=Remove unused podman resources spawned by drone runner +Requires=drone-runner-gc.service + +[Timer] +Unit=drone-runner-gc.service +OnCalendar=hourly +RandomizedDelaySec=600 + +[Install] +WantedBy=timers.target diff --git a/containers/drone-runner/tasks.yml b/containers/drone-runner/tasks.yml new file mode 100644 index 0000000..906f891 --- /dev/null +++ b/containers/drone-runner/tasks.yml @@ -0,0 +1,108 @@ +--- +- hosts: all + name: Drone CI runner agent + tasks: + - name: Get containers UID + ansible.builtin.command: "id -u containers" + register: uid_containers + changed_when: uid_containers.rc != 0 + + - name: Create podman networks + containers.podman.podman_network: + name: "{{ item }}" + recreate: false + state: "present" + become_user: containers + become: true + loop: + - traefik-drone-runner + + # - name: Login to private registry and create ${XDG_RUNTIME_DIR}/containers/auth.json + # become_user: containers + # become: true + # containers.podman.podman_login: + # username: "{{ vault_private_docker_registry_username }}" + # password: "{{ vault_private_docker_registry_password }}" + # registry: "{{ vault_private_docker_registry_url }}" + + - name: Pull an image + become_user: containers + become: true + containers.podman.podman_image: + name: docker.io/drone/drone-runner-docker:linux-{{ [ansible_architecture] | map('extract', arch_friendly_name) | first }} + + - name: Add a drone runner + become_user: containers + become: true + containers.podman.podman_container: + name: drone-runner + image: docker.io/drone/drone-runner-docker:linux-{{ [ansible_architecture] | map('extract', arch_friendly_name) | first }} + state: present + network: + - traefik-drone-runner + security_opt: + - label=type:container_runtime_t + volume: + - /run/user/{{ uid_containers.stdout }}/podman/podman.sock:/var/run/docker.sock:z + label: + io.containers.autoupdate: "registry" + traefik.enable: "true" + traefik.http.routers.drone-runner.entrypoints: "https" + traefik.http.routers.drone-runner.rule: "PathPrefix(`/drone-runner`)" + traefik.http.routers.drone-runner.tls: "true" + traefik.http.routers.drone-runner.tls.certresolver: "wildcard" + traefik.http.routers.drone-runner.service: "drone-runner" + traefik.http.routers.drone-runner.middlewares: "authelia@file" + traefik.http.services.drone-runner.loadbalancer.server.port: "3000" + traefik.docker.network: "traefik-drone-runner" + env: + # https://docs.drone.io/runner/reference/ + DRONE_RPC_PROTO: "https" + DRONE_RPC_HOST: "{{ vault_drone_server_url }}" + DRONE_RPC_SECRET: "{{ vault_drone_rpc_secret }}" + DRONE_RUNNER_NAME: "{{ inventory_hostname_short }}" + DRONE_RUNNER_LABELS: "hostname:{{ inventory_hostname_short }}" + DRONE_RUNNER_CAPACITY: 4 + DRONE_RUNNER_PRIVILEGED_IMAGES: "plugins/docker" + DRONE_UI_USERNAME: "{{ vault_drone_runner_user }}" + DRONE_UI_PASSWORD: "{{ vault_drone_runner_password }}" + # DRONE_DEBUG: "true" + generate_systemd: + path: /home/containers/.config/systemd/user/ + restart_policy: on-failure + names: true + new: true + + - name: Start containers at boot + become_user: containers + become: true + ansible.builtin.systemd: + scope: user + name: container-{{ item }}.service + enabled: true + state: started + daemon_reload: true + loop: + - drone-runner + + - name: Add systemd timer to periodically clean unused volumes + become_user: containers + become: true + ansible.builtin.copy: + src: files/ + dest: /home/containers/.config/systemd/user/ + owner: containers + group: containers + mode: "0644" + + - name: Start garbage collector systemd timer + become_user: containers + become: true + ansible.builtin.systemd: + scope: user + name: "{{ item }}.timer" + enabled: true + state: started + daemon_reload: true + loop: + - drone-runner-gc diff --git a/containers/drone-server/tasks.yml b/containers/drone-server/tasks.yml new file mode 100644 index 0000000..a5e4d4d --- /dev/null +++ b/containers/drone-server/tasks.yml @@ -0,0 +1,87 @@ +--- +- hosts: all + name: Drone CI server coordinator + tasks: + - name: Create podman volumes + containers.podman.podman_volume: + state: present + name: "{{ item }}" + become_user: containers + become: true + loop: + - drone + + - name: Create podman networks + containers.podman.podman_network: + name: "{{ item }}" + recreate: false + state: "present" + become_user: containers + become: true + loop: + - traefik-drone + - gitea-drone + + - name: Pull container images + become_user: containers + become: true + containers.podman.podman_image: + name: docker.io/{{ item }} + loop: + - drone/drone:latest + + - name: Add a drone-server container + become_user: containers + become: true + containers.podman.podman_container: + name: drone-server + image: docker.io/drone/drone:latest + state: present + network: + - traefik-drone + - gitea-drone + volume: + - drone:/data:Z + label: + io.containers.autoupdate: "registry" + traefik.enable: "true" + traefik.http.routers.drone-server.entrypoints: "https" + traefik.http.routers.drone-server.rule: "PathPrefix(`/drone`)" + traefik.http.routers.drone-server.tls: "true" + traefik.http.routers.drone-server.tls.certresolver: "wildcard" + traefik.http.routers.drone-server.service: "drone-server" + traefik.http.routers.drone-server.middlewares: "authelia@file" + traefik.http.services.drone-server.loadbalancer.server.port: "80" + traefik.docker.network: "traefik-drone" + env: + # https://docs.drone.io/server/reference/ + DRONE_GITEA_CLIENT_ID: "{{ vault_drone_gitea_client_id }}" + DRONE_GITEA_CLIENT_SECRET: "{{ vault_drone_gitea_cliet_secret }}" + DRONE_GITEA_SERVER: "https://{{ inventory_hostname }}/git" + DRONE_GIT_ALWAYS_AUTH: "false" + DRONE_RPC_SECRET: "{{ vault_drone_rpc_secret }}" + DRONE_SERVER_HOST: "{{ inventory_hostname }}/drone" + DRONE_SERVER_PROTO: "https" + DRONE_AGENTS_ENABLED: "true" + DRONE_LOGS_TEXT: "true" + DRONE_LOGS_PRETTY: "true" + DRONE_LOGS_COLOR: "true" + DRONE_LOGS_DEBUG: "true" + # DRONE_DEBUG: "true" + generate_systemd: + path: /home/containers/.config/systemd/user/ + restart_policy: on-failure + names: true + new: true + + - name: Start containers at boot + become_user: containers + become: true + ansible.builtin.systemd: + scope: user + name: container-{{ item }}.service + enabled: true + state: started + daemon_reload: true + loop: + - drone-server