/
/
/
Ansible role that deployes services on my runner machine
1---
2# Runner Services - Ghost CMS (Headless Content Management)
3
4- name: Create Ghost configuration directories
5 file:
6 path: "{{ item }}"
7 state: directory
8 owner: "{{ runner_user }}"
9 group: "users"
10 mode: '2775' # setgid bit for inheritance, group writable (umask 002)
11 loop:
12 - "{{ ghost_config_dir }}"
13 - "{{ ghost_config_dir }}/mysql"
14 - "{{ ghost_data_dir }}"
15 - "{{ ghost_content_dir }}"
16 - "{{ ghost_content_dir }}/themes"
17 - "{{ ghost_content_dir }}/images"
18 - "{{ ghost_content_dir }}/files"
19 - "{{ ghost_content_dir }}/adapters"
20
21- name: Generate Ghost environment file
22 template:
23 src: ghost.env.j2
24 dest: "{{ ghost_config_dir }}/ghost.env"
25 owner: "{{ runner_user }}"
26 group: "{{ runner_group }}"
27 mode: '0664'
28 notify: restart ghost
29
30- name: Create Ghost configuration file
31 template:
32 src: ghost-config.json.j2
33 dest: "{{ ghost_content_dir }}/config.production.json"
34 owner: "{{ runner_user }}"
35 group: "{{ runner_group }}"
36 mode: '0664'
37 notify: restart ghost
38
39
40- name: Create Ghost Docker Compose file
41 template:
42 src: ghost-compose.yml.j2
43 dest: "{{ ghost_config_dir }}/docker-compose.yml"
44 owner: "{{ runner_user }}"
45 group: "{{ runner_group }}"
46 mode: '0664'
47 notify: restart ghost
48
49- name: Check if Ghost is already running
50 community.docker.docker_compose_v2:
51 project_src: "{{ ghost_config_dir }}"
52 state: present
53 restarted: false
54 register: ghost_running
55 changed_when: false
56 failed_when: false
57
58- name: Start Ghost services (MySQL + Ghost)
59 community.docker.docker_compose_v2:
60 project_src: "{{ ghost_config_dir }}"
61 state: present
62 register: ghost_start_result
63 check_mode: no
64
65
66- name: Wait for Ghost to be healthy
67 uri:
68 url: "http://localhost:{{ ghost_port }}/ghost/api/admin/site/"
69 method: GET
70 status_code: [200, 403] # 403 is OK for unauthenticated API access
71 register: ghost_health
72 until: ghost_health.status in [200, 403]
73 retries: 30
74 delay: 10
75 when: ghost_start_result is changed
76 check_mode: no
77
78
79
80
81- name: Display Ghost CMS deployment summary
82 debug:
83 msg: |
84 Ghost CMS (Headless) Deployment:
85 - Status: {{ 'Started' if ghost_start_result is changed else 'Already running' }}
86 - Admin Interface: http://{{ ansible_default_ipv4.address }}:{{ ghost_port }}/ghost/
87 - Website: http://{{ ansible_default_ipv4.address }}:{{ ghost_port }}
88 - Content API: http://{{ ansible_default_ipv4.address }}:{{ ghost_port }}/ghost/api/content/
89 - Admin API: http://{{ ansible_default_ipv4.address }}:{{ ghost_port }}/ghost/api/admin/
90 - Database: MySQL {{ mysql_version }}
91 - Configuration: {{ ghost_content_dir }}/config.production.json
92 - Content Storage: {{ ghost_content_dir }}
93 - Database Data: {{ mysql_config_dir }}
94 - Site URL: {{ ghost_url }}
95
96 API Endpoints (for website integration):
97 - Posts: /ghost/api/content/posts/
98 - Pages: /ghost/api/content/pages/
99 - Tags: /ghost/api/content/tags/
100 - Authors: /ghost/api/content/authors/
101 - Settings: /ghost/api/content/settings/
102
103 Features:
104 - Headless CMS for websites and apps
105 - RESTful Content API
106 - Admin API for management
107 - Built-in themes and customization
108 - SEO optimization
109 - Email newsletter integration
110 - Member management and subscriptions
111
112 Management Commands:
113 - ghost-logs.sh - View service logs
114 - ghost-restart.sh - Restart services
115 - ghost-status.sh - Check service status
116 - ghost-backup.sh - Backup content and database
117 - ghost-cli.sh - Ghost CLI commands
118 - ghost-mysql.sh - MySQL management
119 - ghost-api-examples.sh - API usage examples
120
121 Initial Setup:
122 1. Visit http://{{ ansible_default_ipv4.address }}:{{ ghost_port }}/ghost/
123 2. Create your admin account
124 3. Configure your publication settings
125 4. Set up your theme and branding
126 5. Create your first content
127 6. Configure API keys for external access
128
129 Headless/API Integration:
130 - Use Content API key for read-only access
131 - Use Admin API key for content management
132 - Webhook support for real-time updates
133 - JSON responses for all content types
134 - GraphQL support available via plugins