Introduce Kumpir, our new www server, add wordpress role (#26)

* Introduce Kumpir, our new www server, add wordpress role

* move kumpir to services group, use safer distinction for ssl_cert location, reduce www playbook

* set server type to services

* fix typo

* rename service-wordpress to service-nginx-wordpress

* Add service-nginx-etherpad role

* Add ed25519 keypair for system_users when supported.

* Revert "Add ed25519 keypair for system_users when supported."

This reverts commit ffef991ca41185d19953b96439e80b1b9a6ba534.

* Change generated keys format to ed25519

* fix indention of nginx templates, reduce amount of needed tasks by adding extra_opts to unarchive, remove not needed mysql db tasks, make new acme_server default

* Change new default preference for acme servers, marking acme_server zuckerwatte deprecated soon.
This commit is contained in:
prisma01 2019-09-26 22:13:13 +02:00 committed by GitHub
parent f218785e7c
commit b91112516d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 427 additions and 5 deletions

3
.gitignore vendored
View file

@ -2,3 +2,6 @@ playbooks/test.yml
roles/geerlingguy.mysql roles/geerlingguy.mysql
roles/powerdns.pdns roles/powerdns.pdns
roles/lean_delivery.java roles/lean_delivery.java
roles/geerlingguy.php
roles/systemli.etherpad
roles/geerlingguy.nodejs

View file

@ -9,6 +9,7 @@ stdout_callback = yaml
bin_ansible_callbacks = True bin_ansible_callbacks = True
jinja2_extensions = jinja2.ext.do jinja2_extensions = jinja2.ext.do
forks = 10 forks = 10
allow_world_readable_tmpfiles = True
[privilege_escalation] [privilege_escalation]
become = True become = True

View file

@ -219,6 +219,51 @@ wireguard_networks:
- unifi - unifi
- suesskartoffel - suesskartoffel
port: 50035 port: 50035
- ipv4: 10.87.253.72/31
peers:
- kumpir
- ingwer
port: 50036
- ipv4: 10.87.253.74/31
peers:
- kumpir
- spinat
port: 50037
- ipv4: 10.87.253.76/31
peers:
- kumpir
- uffschnitt
port: 50038
- ipv4: 10.87.253.78/31
peers:
- kumpir
- lotuswurzel
port: 50039
- ipv4: 10.87.253.80/31
peers:
- kumpir
- wasserfloh
port: 50040
- ipv4: 10.87.253.82/31
peers:
- kumpir
- linse
port: 50041
- ipv4: 10.87.253.84/31
peers:
- kumpir
- kichererbse
port: 50042
- ipv4: 10.87.253.86/31
peers:
- kumpir
- suesskartoffel
port: 50043
- ipv4: 10.87.253.88/31
peers:
- kumpir
- unifi
port: 50044
fastd_groups: fastd_groups:
- gateways - gateways

View file

@ -0,0 +1,63 @@
---
server_type: "services"
magic: 162
acme_server: linse
php_packages:
- php
- php-fpm
- php-cli
- php-gd
- php-mysql
- php-mbstring
- php-xml
php_webserver_daemon: "nginx"
php_default_version_debian: "7.3"
php_enable_php_fpm: true
php_use_managed_ini: true
php_upload_max_filesize: "512M"
php_post_max_size: "512M"
wp_install_dir: "/var/www/wordpress"
wp_mysql_db: "wordpress"
wp_mysql_user: "wordpress"
wp_mysql_password: "{{ lookup('passwordstore', inventory_hostname_short + '/mysql_wordpress') }}"
wp_service_name: "blog.freifunk-mainz.de"
mysql_root_password: "{{ lookup('passwordstore', inventory_hostname_short + '/mysql_root') }}"
mysql_databases:
- name: "wordpress"
encoding: "utf8mb4"
collation: "utf8mb4_unicode_ci"
- name: "etherpad"
encoding: "utf8mb4"
collation: "utf8mb4_unicode_ci"
mysql_users:
- name: "wordpress"
host: "localhost"
password: "{{ lookup('passwordstore', inventory_hostname_short + '/mysql_wordpress') }}"
priv: "wordpress.*:ALL"
- name: "etherpad"
host: "localhost"
password: "{{ lookup('passwordstore', inventory_hostname_short + '/mysql_etherpad') }}"
priv: "etherpad.*:ALL"
mysql_max_binlog_size: "100M"
mysql_expire_logs_days: "10"
mysql_bind_address: "127.0.0.1"
nginx_ssl_directory: /etc/nginx/ssl/freifunk-mwu.de/
nginx_etherpad_url: "pad.freifunk-mwu.de"
etherpad_db_type: mysql
etherpad_ip: 127.0.0.1
etherpad_port: 9002
etherpad_mysql_database_host: localhost
etherpad_mysql_database_name: etherpad
etherpad_mysql_database_user: etherpad
etherpad_mysql_database_password: "{{ lookup('passwordstore', inventory_hostname_short + '/mysql_etherpad') }}"
etherpad_mysql_database_port: 3306

View file

@ -2,3 +2,4 @@
kichererbse.freifunk-mwu.de kichererbse.freifunk-mwu.de
linse.freifunk-mwu.de linse.freifunk-mwu.de
unifi.freifunk-mwu.de unifi.freifunk-mwu.de
kumpir.freifunk-mwu.de

2
inventory/www Normal file
View file

@ -0,0 +1,2 @@
[www]
kumpir.freifunk-mwu.de

View file

@ -6,3 +6,4 @@
- import_playbook: dns.yml - import_playbook: dns.yml
- import_playbook: buildservers.yml - import_playbook: buildservers.yml
- import_playbook: unifi.yml - import_playbook: unifi.yml
- import_playbook: www.yml

8
playbooks/www.yml Normal file
View file

@ -0,0 +1,8 @@
#!/usr/bin/ansible-playbook
---
- name: Webservers
hosts: www
roles:
- service-nginx-wordpress
- service-nginx-etherpad

View file

@ -1,3 +1,5 @@
- src: geerlingguy.mysql - src: geerlingguy.mysql
- src: powerdns.pdns - src: powerdns.pdns
- src: lean_delivery.java - src: lean_delivery.java
- src: geerlingguy.php
- src: systemli.etherpad

View file

@ -0,0 +1,16 @@
# Ansible Role: Etherpad Nginx Config
Ansible role that installs and configures Nginx for Etherpad.
## Requirements & Dependencies
- service-nginx
- systemli.etherpad
## Variables
```yaml
etherpad_service_name: www.example.com (required)
nginx_ssl_directory: /etc/nginx/ssl/freifunk-mwu.de/ (required)
```

View file

@ -0,0 +1,4 @@
- name: restart nginx
service:
name: nginx
state: restarted

View file

@ -0,0 +1,4 @@
---
dependencies:
- service-nginx
- systemli.etherpad

View file

@ -0,0 +1,10 @@
---
- name: Etherpad | Nginx | Copy virtual host configuration file
template:
src: "nginx-vhost.j2"
dest: /etc/nginx/conf.d/{{ nginx_etherpad_url.split(".")[0] }}.conf
owner: root
group: root
mode: 0644
notify:
- restart nginx

View file

@ -0,0 +1,38 @@
server {
listen 80;
listen [::]:80;
server_name {{ nginx_etherpad_url }};
return 301 https://$http_host$request_uri;
}
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name {{ nginx_etherpad_url }};
ssl_certificate {{ nginx_ssl_directory }}fullchain.pem;
ssl_certificate_key {{ nginx_ssl_directory }}privkey.pem;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://localhost:9002/;
proxy_set_header Host $host;
proxy_pass_header Server;
# be careful, this line doesn't override any proxy_buffering on set in a conf.d/file.conf
proxy_buffering off;
proxy_set_header X-Real-IP $remote_addr; # http://wiki.nginx.org/HttpProxyModule
proxy_set_header X-Forwarded-For $remote_addr; # EP logs to show the actual remote IP
proxy_set_header X-Forwarded-Proto $scheme; # for EP to set secure cookie flag when https is used
proxy_set_header Host $host; # pass the host header
proxy_http_version 1.1; # recommended with keepalive connections
# WebSocket proxying - from http://nginx.org/en/docs/http/websocket.html
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}

View file

@ -0,0 +1,34 @@
<p align="center">
<img width="150" height="150" src="https://upload.wikimedia.org/wikipedia/commons/9/98/WordPress_blue_logo.svg">
</p>
# Ansible Role: WordPress
Ansible role that installs and configures WordPress with Nginx.
Features include:
- Installation of any WordPress version to specified directory
- Configuration of `wp-config.php`
- Fetch random salts for wp-config.php (https://api.wordpress.org/secret-key/1.1/salt/)
## Requirements & Dependencies
- Ansible 1.4 or higher
- Curl
## Variables
Here is a list of all the default variables for this role, which are also available in `defaults/main.yml`.
```yaml
wp_version: latest
wp_install_dir: '/var/www/html'
wp_db_name: "{{ wp_mysql_db }}" (required)
wp_db_user: "{{ wp_mysql_user }}" (required)
wp_db_password: "{{ wp_mysql_password }}" (required)
wp_db_host: 'localhost'
wp_db_charset: 'utf8mb4'
wp_db_collate: 'utf8mb4_unicode_ci'
wp_table_prefix: 'wp_'
wp_debug: false
wp_admin_email: 'admin@example.com'
site_name: "{{ wp_sitename }}" (requires)
```

View file

@ -0,0 +1,13 @@
---
wp_version: latest
wp_install_dir: '/var/www/html'
wp_db_name: "{{ wp_mysql_db }}"
wp_db_user: "{{ wp_mysql_user }}"
wp_db_password: "{{ wp_mysql_password }}"
wp_db_host: 'localhost'
wp_db_charset: 'utf8mb4'
wp_db_collate: 'utf8mb4_unicode_ci'
wp_table_prefix: 'wp_'
wp_debug: false
wp_admin_email: 'admin@example.com'
site_name: "{{ wp_sitename }}"

View file

@ -0,0 +1,4 @@
- name: restart nginx
service:
name: nginx
state: restarted

View file

@ -0,0 +1,5 @@
---
dependencies:
- service-nginx
- geerlingguy.php
- geerlingguy.mysql

View file

@ -0,0 +1,45 @@
---
- name: Wordpress | Create directory
file:
path: "{{ wp_install_dir }}"
state: directory
mode: 0755
- name: Wordpress | Extract archive in {{ wp_install_dir }}
unarchive:
src: "http://wordpress.org/wordpress-{{ wp_version }}.tar.gz"
dest: "{{ wp_install_dir }}"
extra_opts:
- --strip-components=1
remote_src: yes
- name: Wordpress | Fetch random salts for wp-config.php
delegate_to: localhost
command: curl https://api.wordpress.org/secret-key/1.1/salt/
become: False
args:
warn: false
register: 'wp_salt'
- name: Wordpress | Copy wp-config.php file
template:
src: wp-config.php.j2
dest: "{{ wp_install_dir }}/wp-config.php"
- name: Wordpress | Change ownership of installation directory
file:
path: "{{ wp_install_dir }}"
owner: www-data
group: www-data
state: directory
recurse: yes
- name: Wordpress | Nginx | Copy virtual host configuration file
template:
src: "nginx-vhost.j2"
dest: /etc/nginx/conf.d/{{ wp_service_name.split(".")[0] }}.conf
owner: root
group: root
mode: 0644
notify:
- restart nginx

View file

@ -0,0 +1,52 @@
server {
listen 80;
listen [::]:80;
server_name {{ wp_service_name }};
return 301 https://$http_host$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name {{ wp_service_name }};
ssl_certificate {{ nginx_ssl_directory }}fullchain.pem;
ssl_certificate_key {{ nginx_ssl_directory }}privkey.pem;
ssl_prefer_server_ciphers on;
root {{ wp_install_dir }};
# Add index.php to the list if you are using PHP
index index.php;
server_name {{ wp_service_name }};
client_max_body_size 1024M;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
#try_files $uri $uri/ =404;
try_files $uri $uri/ /index.php$is_args$args;
}
location = /favicon.ico { log_not_found off; access_log off; }
location = /robots.txt { log_not_found off; access_log off; allow all; }
location ~* \.(css|gif|ico|jpeg|jpg|js|png)$ {
expires max;
log_not_found off;
}
# pass the PHP scripts to FastCGI server listening on socket
location ~ \.php$ {
try_files $uri =404;
include /etc/nginx/fastcgi_params;
fastcgi_read_timeout 3600s;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass 127.0.0.1:9000;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_index index.php;
}
}

View file

@ -0,0 +1,60 @@
<?php
/**
* The base configurations of the WordPress.
*
* This file has the following configurations: MySQL settings, Table Prefix,
* Secret Keys, and ABSPATH. You can find more information by visiting
* {@link http://codex.wordpress.org/Editing_wp-config.php Editing wp-config.php}
* Codex page. You can get the MySQL settings from your web host.
*
* This file is used by the wp-config.php creation script during the
* installation. You don't have to use the web site, you can just copy this file
* to "wp-config.php" and fill in the values.
*
* @package WordPress
*/
// ** MySQL settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define('DB_NAME', '{{wp_db_name}}');
/** MySQL database username */
define('DB_USER', '{{wp_db_user}}');
/** MySQL database password */
define('DB_PASSWORD', '{{wp_db_password}}');
/** MySQL hostname */
define('DB_HOST', '{{wp_db_host}}');
/** Database Charset to use in creating database tables. */
define('DB_CHARSET', '{{wp_db_charset}}');
/** The Database Collate type. Don't change this if in doubt. */
define('DB_COLLATE', '{{wp_db_collate}}');
/**#@+
* Authentication Unique Keys and Salts.
*
* Change these to different unique phrases!
* You can generate these using the {@link https://api.wordpress.org/secret-key/1.1/salt/ WordPress.org secret-key service}
* You can change these at any point in time to invalidate all existing cookies. This will force all users to have to log in again.
*
* @since 2.6.0
*/
{{wp_salt.stdout}}
/**#@-*/
/**
* WordPress Database Table prefix.
*
* You can have multiple installations in one database if you give each a unique
* prefix. Only numbers, letters, and underscores please!
*/
$table_prefix = '{{wp_table_prefix}}';
/**
* For developers: WordPress debugging mode.
*
* Change this to true to enable the display of notices during development.
* It is strongly recommended that plugin and theme developers use WP_DEBUG
* in their development environments.
*/
define('WP_DEBUG', {{wp_debug}});
/* That's all, stop editing! Happy blogging. */
/** Absolute path to the WordPress directory. */
if ( !defined('ABSPATH') )
define('ABSPATH', dirname(__FILE__) . '/');
/** Sets up WordPress vars and included files. */
require_once(ABSPATH . 'wp-settings.php');

View file

@ -23,9 +23,13 @@ server {
charset utf-8; charset utf-8;
server_tokens off; server_tokens off;
{% if acme_server == 'zuckerwatte' %}
ssl_certificate /etc/nginx/ssl/{{ inventory_hostname_short }}.{{ http_domain_external }}/fullchain.pem; ssl_certificate /etc/nginx/ssl/{{ inventory_hostname_short }}.{{ http_domain_external }}/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/{{ inventory_hostname_short }}.{{ http_domain_external }}/privkey.pem; ssl_certificate_key /etc/nginx/ssl/{{ inventory_hostname_short }}.{{ http_domain_external }}/privkey.pem;
{% else %}
ssl_certificate /etc/nginx/ssl/{{ http_domain_external }}/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/{{ http_domain_external }}/privkey.pem;
{% endif %}
include /etc/nginx/snippets/letsencrypt-acme-challenge.conf; include /etc/nginx/snippets/letsencrypt-acme-challenge.conf;

View file

@ -1,12 +1,19 @@
#!/bin/sh #!/bin/sh
{% if acme_server == 'zuckerwatte' %}
DOMAINS="{{ inventory_hostname_short }}.{{ http_domain_external }}" DOMAINS="{{ inventory_hostname_short }}.{{ http_domain_external }}"
{% else %}
DOMAINS={{ http_domain_external }}
{% endif %}
LOCAL_DIR="/etc/nginx/ssl" LOCAL_DIR="/etc/nginx/ssl"
for DOMAIN in $DOMAINS; for DOMAIN in $DOMAINS;
do do
#Get Certs #Get Certs
{% if acme_server == 'zuckerwatte' %}
rsync --delete -rz -e 'ssh -i /home/admin/.ssh/id_rsa -p 23' cert@{{ acme_server }}.{{ http_domain_internal }}:$DOMAIN/ $LOCAL_DIR/$DOMAIN rsync --delete -rz -e 'ssh -i /home/admin/.ssh/id_rsa -p 23' cert@{{ acme_server }}.{{ http_domain_internal }}:$DOMAIN/ $LOCAL_DIR/$DOMAIN
{% else %}
rsync --delete -rz -e 'ssh -i /home/admin/.ssh/id_ed25519 -p 23' cert@{{ acme_server }}.{{ http_domain_internal }}:$DOMAIN/ $LOCAL_DIR/$DOMAIN
{% endif %}
#Fix Permissions #Fix Permissions
chmod 0550 $LOCAL_DIR/$DOMAIN chmod 0550 $LOCAL_DIR/$DOMAIN

View file

@ -11,7 +11,7 @@
shell: "{{ item.shell }}" shell: "{{ item.shell }}"
home: "{{ item.home }}" home: "{{ item.home }}"
generate_ssh_key: "{{ item.generate_ssh_key }}" generate_ssh_key: "{{ item.generate_ssh_key }}"
ssh_key_bits: "{{ item.ssh_key_bits }}" ssh_key_type: "{{ item.ssh_key_type }}"
state: "{{ item.state }}" state: "{{ item.state }}"
loop: "{{ system_users }}" loop: "{{ system_users }}"

View file

@ -6,8 +6,8 @@ system_users:
home: "/home/admin" home: "/home/admin"
state: "present" state: "present"
ssh_keys: "{{ ssh_keys_admin_team }}" ssh_keys: "{{ ssh_keys_admin_team }}"
ssh_key_type: ed25519
generate_ssh_key: "yes" generate_ssh_key: "yes"
ssh_key_bits: 4096
admin_users: admin_users: