Ghost Hands - Automating The Stronghold With Ansible And Podman
Mission Update
Now we automate.
The pod.
The proxy.
The secrets.
One playbook to conjure the setup, one command to repeat the ritual.
Requirements
- Ansible (core +
community.containers
) - Podman configured for rootless ops
- X509 certs or automation for Let's Encrypt
- Directory structure with:
-
roles/semaphore/tasks/main.yml
-
files/nginx.conf
-
files/cert.pem, key.pem
(or auto-gen task)
-
Playbook Strategy
- Create Podman pod
- Deploy MySQL container
- Deploy Semaphore UI container
- Deploy NginX container with volumes mounted
Secret Externalization
Store credentials in group_vars/containers.yml
and encrypt with Ansible Vault.
Step 1: Create The Pod
- name: Create the pod containers.podman.podman_pod: name: p_semaphore state: created ports: - "4430:443"
Step 2: Activate the MySQL Container
- name: Create the MySQL container containers.podman.podman_container: name: semaphore_mysql pod: p_semaphore state: started rm: true detach: true image: docker.io/mysql:lts volumes: - semaphore_mysql:/var/lib/mysql env: MYSQL_RANDOM_ROOT_PASSWORD: 'yes' MYSQL_DATABASE: semaphore MYSQL_USER: semaphore MYSQL_PASSWORD: " {{ semaphore_mysql_pw }} "
Step 3: Initiate the Semaphore container
- name: Create the Semaphore container containers.podman.podman_container: name: semaphore pod: p_semaphore state: started rm: true detach: true image: docker.io/semaphoreui/semaphore:latest env: SEMAPHORE_DB_USER: semaphore SEMAPHORE_DB_PASS: " {{ semaphore_mysql_pw }} " SEMAPHORE_DB_HOST: 127.0.0.1 SEMAPHORE_DB_PORT: 3306 SEMAPHORE_DB_DIALECT: mysql SEMAPHORE_DB: semaphore SEMAPHORE_PLAYBOOK_PATH: /tmp/semaphore/ SEMAPHORE_ADMIN_PASSWORD: " {{ semaphore_admin_pw }} " SEMAPHORE_ADMIN_NAME: admin SEMAPHORE_ADMIN_EMAIL: admin@localhost SEMAPHORE_ADMIN: admin SEMAPHORE_ACCESS_KEY_ENCRYPTION: gs72mPntFATGJs9qK0pQ0rKtfidlexiMjYCH9gWKhTU= SEMAPHORE_LDAP_ACTIVATED: 'no' TZ: UTC
Step 4: The NginX Reverse Proxy
- name: Create the NginX container containers.podman.podman_container: name: semaphore_proxy pod: p_semaphore state: started rm: true detach: true image: docker.io/library/nginx volumes: - " {{ role_path }} /files/nginx.conf:/etc/nginx/conf.d/default.conf:ro" - " {{ role_path }} /files/cert.pem:/etc/nginx/cert.pem:ro" - " {{ role_path }} /files/key.pem:/etc/nginx/key.pem:ro"
Step 5: Verify
Log in.
Verify the configuration.
Monitor the logs with podman pod logs p_semaphore
.
Final Signal
The stronghold stands.
Provisioned in silence. Hardened by code.
But this is just the surface. A faint signal.
There is much to do for a strong signal.
Need the full Ansible role?
- Variables ready
- Templates in place
- Handlers sharpened
- Deploy once, repeat forever
Buy the hardened role + full guide - forged in the silence.
Whisper to DeadSwitch on Matrix: @deadswitch:matrix.org
Maybe the Ghost signals back.
DeadSwitch | The Silent Architect
In silence, I rise. In structure, I endure.