role_compositional
Ansible Collection - compositionalenterprises.ourcompose
This role sets up a VM to host what amounts to a cloud-in-a-box; a combination of various cloud services all hosted in subdirectories of a given domain.
Requirements
Here is our requirements.txt that we use when we set up the environment for our playbooks to execute in:
---
- src: nickjj.docker
name: docker
- src: [email protected]:compositionalenterprises/role-compositional
scm: git
version: master
name: compositional
- src: geerlingguy.certbot
name: certbot
- src: oefenweb.swapfile
name: swapfile
This allows for setting up docker, certbot, and a generous swapfile on the server. However, the only obvious requirement is that docker is set up. Additionally, it is not required to be set up externally facing. It is sufficient to just have it running on the server locally.
SSL Certificates
This role assumes that the SSL cert is set up somewhere on the server where docker can mount it as a volume to wherever inside of the proxy container it needs to go. By default:
compositional_nginx_cert_volume: '/etc/letsencrypt:/etc/letsencrypt'
compositional_nginx_cert_fullchain: "/etc/letsencrypt/live/{{ environment_domain }}/fullchain.pem"
compositional_nginx_cert_privkey: "/etc/letsencrypt/live/{{ environment_domain }}/privkey.pem"
Python Libraries
On the remote host, the docker library needs to be installed. This can be done by simply installing it with the default package manager. However, nickjj.docker
(above) creates a virtualenv that can be used by passing the ansible python interpreter as an argument to the role:
- role: compositional
ansible_python_interpreter: "/usr/bin/env python3-docker"
Role Variables
This will always be changing and being added to. However, there are a couple categories that are independent of services, and several that are applicable to all of the services:
General
# OVERRIDE THIS!!!!
compositional_database_root_password: 'testpassword'
# The enumeration of the services to be installed.
# You'll probably want to override this with a subset
# of only the services that you want installed.
compositional_services:
- 'bitwarden'
- 'bookstack'
- 'commandcenter'
- 'firefly'
- 'kanboard'
- 'nextcloud'
- 'rundeck'
- 'wordpress'
Environment
# The domain that will be pointing to the server's IP
environment_domain: 'example.com'
Services
All of the services have variables with the prefix: compositional_<service name>_
.
Common
There are several variables that are typical of all of the services using that prefix. These are all directly associated with their related docker_compose ansible module options:
There are two others that are specific to this role:
version
: The container image tag version to pullstorage
: Whether this should go underlocal
orremote
storage. Note thatremote
storage is simply a directly under/srv
that is meant to be mounted to an external volume of some kind, but is otherwise functionally the same aslocal
.
Database Backend Services
All services that have a database backend (which is most of them) have a variable to set the password for the account that will be created in that database for them to use. THIS IS INSECURE BY DEFAULT AND SHOULD BE OVERRIDDEN FOR INSTANCES DEPLOYED IN PRODUCTION. They come in the form of compositional_<service name>_backend_password
.
Bind Mountpoints
These mountpoints will be able to be set up on any service to be able to bind-mount static assets into the frontend proxy in order to avoid contacting backend servers and speed up the transmission of the assets. They come in the form of compositional_< service >_bind_mountpoints
.
This variable is in the following format:
compositional_firefly_bind_mountpoints:
- {location: '/firefly/v1/css/', directory: '/var/www/firefly-iii/public/v1/css'}
- {location: '/firefly/v1/fonts/', directory: '/var/www/firefly-iii/public/v1/fonts'}
- {location: '/firefly/v1/images/', directory: '/var/www/firefly-iii/public/v1/images'}
- {location: '/firefly/v1/js/', directory: '/var/www/firefly-iii/public/v1/js'}
- {location: '/firefly/v1/lib/', directory: '/var/www/firefly-iii/public/v1/lib'}
So this is a list of dictionaries. The dictionaries have the keys location
, and directory
. The location
is the subdomain path that should be intercepted and redirected to the local bindmount. The directory
key is the location within the image where the assets are location. Alternatively, if the path in the directory
key starts with /srv
, the role will look at the host's /srv
directory for that location, rather than inside the image.
NOTE: This is hard-coded right now. If it becomes an issue, we can make the /srv
location a variable, but for now all directory
keys that point to /srv
are expected to be on the host.
Domain Redirects
Any site that has its DNS pointing to an instance can have an alternate DNS entry redirected. This comes in the form of:
compositional_domain_redirects:
- {domain: 'ourcomposecast.com', redirect: 'https://ourcompose.com/jekyll', cert: 'live/ourcomposecast.com/fullchain.pem'}
- {domain: 'ourcomposesignup.com', redirect: 'https://ourcompose.com/commandcenter', cert: 'live/ourcomposesignup.com/fullchain.pem'}
compositional_domain_redirects: []
If there is no cert, the HTTPS
requests will NOT be able to be accepted.
NOTE: If there is any abuse of this functionality in the future, this could be restricted to redirects pointing to only locations within the {{ environment_domain }}
.
Jekyll
Jekyll has a couple of others to use:
compositional_jekyll_git_url
: The URL to use for the Jekyll theme as a git repocompositional_jekyll_git_branch
: The branch of that git repo to usecompositional_jekyll_extra_commands
: This can be used to execute arbitrary commands inside of the container before the command to build the website is given. This is useful for installing additional tools, or copying down additional materials that need to be included in the container at runtime. This allows for us to provide customized runtimes while still utilizing the upstream container.
Rundeck
compositional_rundeck_api_tokens_duration_max
: Set to '0' by default, this eliminates any limits on API token lifetime length. Set this to a number of minutes to enforce that limit.compositional_rundeck_additional_setup
: This is another place to execute arbitrary commands as root within the container. This is especially useful for installing requirements if scripts are going to be running on the host server's environment. The distro this is based off of is Ubuntu, so make sure toapt update
before trying to install anything.
CommandCenter and Portal
CommandCenter and Portal allow us to store their production_key
and production.yml.enc
file contents in the following variables:
compositional_commandcenter_production_key
: Can be found atconfig/credentials
folder of commandcenter application, sample keys are passed by defaultcompositional_commandcenter_production_yml_enc
: Can be found atconfig/credentials
folder of commandcenter application, sample keys are passed by defaultcompositional_portal_production_key
: Can be found atconfig/credentials
folder of portal application, sample keys are passed by defaultcompositional_portal_production_yml_enc
: Can be found atconfig/credentials
folder of portal application, sample keys are passed by default
This should probably be vaulted, but as they are by default, you will be able to get an instance spun up and working by default.
See the CommandCenter Repo - Passing Production Keys for more information on updating rails credentials files. Please also note with the default keys setup we run, the keys can be updated from a commandline interface within the container using EDITOR=vim RAILS_ENV=production rails credentials:edit -e production
New Services
Whenever new services are added, we should make sure they are doing the same things that the other ones are. It's typically easiest to start off finding the service that's most similar to the new one. The files for the NGINX configuration file and the task file can be copied, renamed, and edited. Then the variables section can be copied to a new section and renamed, and the service added to the list of services in the defaults/main.yml
file.
Setup Steps
New services should include the following setup steps:
- NGINX Configuration Template
- Database initialization check
- Database setup script
docker_compose
setup- Bind Mountpoints
- Script Execution (Coming Soon)
- Default Login Account (Coming Later)
- Unified Account Management (Coming Much Later)
Requirements
- Open Source
- Able to run in a subdirectory
- Able to use MariaDB/MySQL as a backend or have a self-contained backend (other backends coming later)
- Upstream or otherwise maintained docker image (We maintain our own in special circumstances)
Examples
#
# This playbook sets up a SSL-encrypted server running nextcloud with default
# frontends and backends, and default passwords. FOR TESTING ONLY!!!
#
- name: Roles in Common
hosts: all
become: yes
vars_files:
- ../environment/group_vars/all/all.yml
vars:
docker__pip_packages:
- "docker"
- "python-apt"
certbot_auto_renew_options: "--quiet --no-self-upgrade --pre-hook='docker stop proxy' --post-hook='docker start proxy'"
certbot_admin_email: "{{ environment_admin }}@{{ environment_domain }}"
certbot_create_if_missing: True
certbot_install_from_source: True
certbot_create_standalone_stop_services:
- 'docker'
certbot_certs:
- domains:
- "{{ environment_domain }}"
pre_tasks:
- name: Update all packages on the system
apt:
name: '*'
state: latest
update_cache: True
roles:
- role: swapfile
swapfile_size: '4G'
- role: docker
- role: certbot
- role: compositional
ansible_python_interpreter: "/usr/bin/env python3-docker"
License
MIT
Author Information
Andrew Cziryak
ansible-galaxy install compositionalenterprises/role-compositional