Skip to content

Commit

Permalink
Deploy to Dreamhost (and with a proper cert!)
Browse files Browse the repository at this point in the history
I thought I'd be using Kubernetes on AWS but I had trouble figuring
it all out since I'm a noob at both of those things.

So let's do the simplest thing that will work in the interests of
shipping early and often.

How:
* An (Openstack) instance on Dreamhost DreamCompute created with a
  Fedora 32 image and the lowest, cheapest specs.

* Some ansible to provision that host with what we need, and bring
  up our service.

* Docker-compose in production without any front end. (It
  seems like most people are using nginx. Maybe I'll need that
  later, but so far it seems I can get away without it.)

* Note that docker compose starts up separate container for postgres
  just like we do in development. So the database is just sitting
  there in the VM's volume for now. (Might want to do something
  different with that in future.)

* Note the TiddlyWiki files themselves are stored in S3. (That's not
  new here, that part has been working for a while now.)

* Letsencrypt SSL cert. The DNS is handled in AWS's Route 43, for which
  there is a certbot plugin that supports the cname creation method used
  to verify things for letsencrypt.

* Change the name of the certs to prevent confusion. We can use the
  same name for devel and for prod, but if it's call localssl in prod
  that's gonna be confusion. Also move where the local certs are
  kept so there's a chance we can still run the prod container
  locally. There's some inconsistency now between the way certs are
  done in dev and in prod. Will worry about that later.

There's still more to do, e.g. we probably don't come back up after
a restart, hence this isn't quite production ready.

I'm not planning to "go live" in a big way yet, but I'm going to
leave the server up for a bit and declare version 0.0.1 soon.
  • Loading branch information
simonbaird committed Feb 12, 2021
1 parent 05c74c9 commit 981958a
Show file tree
Hide file tree
Showing 10 changed files with 170 additions and 12 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ rails/public/packs/
rails/public/packs-test/
rails/config/master.key
.postgresql-data
etc/certs
certs
etc/build-info.txt
etc/certbot-dns-user-credentials.yml
2 changes: 1 addition & 1 deletion Dockerfile.base
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ RUN echo deb https://dl.yarnpkg.com/debian/ stable main > /etc/apt/sources.list.
RUN apt-get update -qq && apt-get install -y --no-install-recommends postgresql-client nodejs yarn vim-tiny

# Install self-signed SSL cert
COPY --chown=$APP_USER:$APP_USER etc/certs $CERT_PATH
COPY --chown=$APP_USER:$APP_USER ./certs $CERT_PATH

# Install script to help start rails
COPY --chown=$APP_USER:$APP_USER etc/start-rails.sh /bin
Expand Down
1 change: 0 additions & 1 deletion Dockerfile.prod
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ USER $APP_USER
ENV RAILS_ENV=production
ENV APP_DATABASE_PASSWORD=notsecure123
ENV RAILS_SERVE_STATIC_FILES=true
ENV RAILS_LOG_TO_STDOUT=true

# Copy our app into the container
# Ignores things listed in .dockerignore
Expand Down
28 changes: 24 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ build-prod:
./etc/create-build-info.sh
docker-compose -f docker-compose-prod.yml build prod

# FIXME: The auth doesn't work from make for some reason
push-prod:
@echo docker push sbaird/tiddlyhost

rails-init:
docker-compose run --rm base bash -c "bundle install && \
bundle exec rails webpacker:install && \
Expand Down Expand Up @@ -85,16 +89,32 @@ cleanup:

# Generate an SSL cert
# (If the cert exists, assume the key exists too.)
cert: etc/certs/localssl.cert
cert: certs/ssl.cert

etc/certs/localssl.cert:
certs/ssl.cert:
@cd ./etc && ./create-local-ssl-cert.sh

clear-cert:
@rm ./etc/certs/localssl.cert
@rm ./etc/certs/localssl.key
@rm ./certs/ssl.cert
@rm ./certs/ssl.key

redo-cert: clear-cert cert

github-url:
@echo https://github.com/simonbaird/tiddlyhost

PLAY = ansible-playbook -i ansible/inventory.yml
deploy:
$(PLAY) ansible/deploy.yml

deploy-deps:
$(PLAY) -v ansible/deploy.yml --tags=deps

deploy-certs:
$(PLAY) -v ansible/deploy.yml --tags=certs

deploy-app:
$(PLAY) -v ansible/deploy.yml --tags=app

deploy-ssh:
@ssh fedora@tiddlyhost.com
129 changes: 129 additions & 0 deletions ansible/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@

- hosts: all
become: yes
become_user: root

vars:
- home_dir: /home/{{ ansible_user }}
root_home_dir: /root

certbot_dns_credentials: ../etc/certbot-dns-user-credentials.yml
docker_compose_file: ../docker-compose-prod.yml

cert_host: tiddlyhost.com
letsencrypt_dir: /etc/letsencrypt/live/{{ cert_host }}
certs_dir: "{{ home_dir }}/certs"

tasks:

- name: Add repo for docker-ce
command:
cmd: dnf config-manager --add-repo https://download.docker.com/linux/fedora/docker-ce.repo
creates: /etc/yum.repos.d/docker-ce.repo
warn: false
tags: deps

- name: Install docker and certbot
dnf:
state: present
name:
- docker-ce
- docker-ce-cli
- containerd.io
- certbot
tags: deps

- name: Start docker
systemd:
name: docker
state: started
enabled: yes
tags: deps

- name: Pip install docker-compose and certbot-dns-route53
pip:
name:
- docker-compose
- certbot-dns-route53
tags: deps

- name: Create dir for certbot aws credentials
file:
path: "{{ root_home_dir }}/.aws"
state: directory
tags: certs

- name: Install AWS credentials for certbot
copy:
src: "{{ certbot_dns_credentials }}"
dest: "{{ root_home_dir }}/.aws/credentials"
tags: certs

- name: Create a cert if it doesn't exist
command:
cmd: >-
certbot certonly
-d {{ cert_host }} -d *.{{ cert_host }}
--dns-route53
-n --agree-tos -m simon.baird@gmail.com
creates: "{{ letsencrypt_dir }}/fullchain.pem"
tags: certs

- name: Renew certs maybe
command:
# TODO: The post-hook is untested, not sure if it will work
cmd: certbot renew --post-hook "docker-compose restart prod"
register: certbot_renew
tags: certs

- name: Show renew output
debug:
var: certbot_renew.stdout_lines
tags: certs

- name: Create dir for certs
file:
path: "{{ certs_dir }}"
state: directory
tags: certs

- name: Copy cert files to where the container looks for them
# TODO: It would be better to only do this if they changed
command:
cmd: cp {{ letsencrypt_dir }}/{{ item.from }} {{ certs_dir }}/{{ item.to }}
with_items:
- from: fullchain.pem
to: ssl.cert
- from: privkey.pem
to: ssl.key
tags: certs

- name: Update owner of the cert files
file:
path: "{{ certs_dir }}"
recurse: yes
owner: "{{ ansible_user }}"
group: "{{ ansible_user }}"
tags: certs

- name: Copy docker-compose file
become: no
copy:
src: "{{ docker_compose_file }}"
dest: "{{ home_dir }}/docker-compose.yml"
tags: app

- name: Pull latest images
# So docker-compose doesn't try to build
command:
cmd: docker-compose pull -q
tags: app

- name: Start our service
command:
cmd: docker-compose up --detach
environment:
# (Maybe we do need to copy up the key file)
RAILS_MASTER_KEY: "{{ lookup('file', '../rails/config/master.key') }}"
tags: app
4 changes: 4 additions & 0 deletions ansible/inventory.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
all:
hosts:
tiddlyhost.com:
ansible_user: fedora
File renamed without changes.
7 changes: 6 additions & 1 deletion docker-compose-prod.yml
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
services:

prod:
image: tiddlyhost:latest
image: sbaird/tiddlyhost:latest

build:
context: .
dockerfile: Dockerfile.prod

ports:
- "443:3000"
- "80:3000"

depends_on:
- db

volumes:
- ./certs/ssl.cert:/opt/certs/ssl.cert:Z
- ./certs/ssl.key:/opt/certs/ssl.key:Z

environment:
RAILS_MASTER_KEY:

Expand Down
6 changes: 3 additions & 3 deletions etc/create-local-ssl-cert.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ openssl x509 -req -sha256 -days 365 -in server.csr -signkey server.key -out serv
# Clean up
rm server.pass.key
rm server.csr
mv server.key certs/localssl.key
mv server.crt certs/localssl.cert
mv server.key ../certs/ssl.key
mv server.crt ../certs/ssl.cert

echo Created certs/localssl.cert and certs/localssl.key
echo Created ../certs/ssl.cert and ../certs/ssl.key
2 changes: 1 addition & 1 deletion etc/start-rails.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
rm -f tmp/pids/server.pid

# Start rails
exec bin/rails s -p 3000 -b 'ssl://0.0.0.0?key=/opt/certs/localssl.key&cert=/opt/certs/localssl.cert'
exec bin/rails s -p 3000 -b 'ssl://0.0.0.0?key=/opt/certs/ssl.key&cert=/opt/certs/ssl.cert'

0 comments on commit 981958a

Please sign in to comment.