Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions inventory/host_vars/vote.freifunktion.net
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
vote_secret_cookie_token: !vault |
$ANSIBLE_VAULT;1.1;AES256
39393166646365343532383462623862666434353665313739643435323133353030636237613665
3566353737643562323863333134656231316538646365360a663937656362333264323936633638
31386533376362363965333139383138383565363363623638633966333430393534396163326662
3966333463336539640a333031663262336535386461613735333734353162633039393835353139
61386166636230666233613864343364313361383130386362396366366634326464386435303936
38636538393564313865333438376561316332386130306334633663393034346430393931613435
39316466633633346436643236633432343161616532343832353165313138336638336234373137
33343164656434396239
vote_devise_secret: !vault |
$ANSIBLE_VAULT;1.1;AES256
36363966373631636433646532366130346234613637393533643765623066353763626135373435
6633383363383136316364636534373135383461373639380a393936396563373361326464616434
33656630353061303561306431643532353632366138366335666465663962613865323334613731
6565623038383033370a366165323137666535366464393062333230396333316131306137323035
31306662646462303331343866313731316665623832346135343136633966356238613035616265
33633236366430663930303135323133666162663830653630333466376162626539306233353435
32633931646135383236376133303035376538333333373734313935656334353263333665333462
34623438323737333933
vote_smtp_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
36366462616633373165656365623732326233636535643064306539343031633730346664373736
3833653932616266313239336363666139353033343663620a396331366433643233353430343433
66323037616432663731333063363733616166646135623436396239393631356235373364353137
3232613463653662390a343061656432656630333339303964376462336162343837373762623364
3162
128 changes: 128 additions & 0 deletions roles/docker/templates/vote.freifunktion.net.yml.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
services:
app:
container_name: loomio-app
image: ${LOOMIO_CONTAINER_IMAGE}:${LOOMIO_CONTAINER_TAG}
restart: unless-stopped
healthcheck:
test: ['CMD-SHELL', 'curl --fail http://localhost:3000/ || exit 1']
expose:
- 3000
env_file: ./.env
environment:
- VIRTUAL_HOST=${CANONICAL_HOST}
- LETSENCRYPT_HOST=${CANONICAL_HOST}
volumes:
- ./uploads:/loomio/public/system
- ./storage:/loomio/storage
- ./files:/loomio/public/files
- ./plugins:/loomio/plugins/docker
- ./import:/import
- ./tmp:/loomio/tmp
networks:
- main
depends_on:
- db
- redis

worker:
container_name: loomio-worker
image: ${LOOMIO_CONTAINER_IMAGE}:${LOOMIO_CONTAINER_TAG}
restart: always
networks:
- main
env_file: ./.env
environment:
- TASK=worker
volumes:
- ./uploads:/loomio/public/system
- ./storage:/loomio/storage
- ./files:/loomio/public/files
- ./plugins:/loomio/plugins/docker
- ./tmp:/loomio/tmp

db:
container_name: loomio-db
image: postgres:${POSTGRES_CONTAINER_TAG}
restart: unless-stopped
healthcheck:
test: ['CMD', 'pg_isready', '-U', 'postgres']
networks:
- main
env_file: ./.env
volumes:
- ./pgdata:/pgdata
- ./pgdumps:/pgdumps
environment:
- PGDATA=/pgdata

redis:
container_name: loomio-redis
image: redis:5.0
restart: unless-stopped
healthcheck:
test: ['CMD', 'redis-cli', 'ping']
networks:
- main

mailin:
container_name: loomio-mailin
image: ${MAILIN_CONTAINER_IMAGE}:${MAILIN_CONTAINER_TAG}
restart: unless-stopped
networks:
- main
ports:
- "25:25"
environment:
- WEBHOOK_URL=http://app:3000/email_processor/

channels:
container_name: loomio-channels
image: loomio/loomio_channel_server
restart: unless-stopped
networks:
- main
env_file: ./.env
depends_on:
- redis
environment:
- VIRTUAL_HOST=channels.${CANONICAL_HOST}
- LETSENCRYPT_HOST=channels.${CANONICAL_HOST}

hocuspocus:
container_name: loomio-hocuspocus
image: loomio/loomio_channel_server
restart: unless-stopped
networks:
- main
env_file: ./.env
environment:
- APP_URL=http://app:3000
- VIRTUAL_HOST=hocuspocus.${CANONICAL_HOST}
- LETSENCRYPT_HOST=hocuspocus.${CANONICAL_HOST}
command: npm run hocuspocus

pgbackups:
image: prodrigestivill/postgres-backup-local
restart: always
user: postgres:postgres
networks:
- main
volumes:
- ./pgdumps:/backups
links:
- db
depends_on:
- db
environment:
- POSTGRES_HOST=db
- POSTGRES_DB=loomio_production
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=password
- POSTGRES_EXTRA_OPTS=-Z6 --schema=public --blobs
- SCHEDULE=@daily
- BACKUP_KEEP_DAYS=7
- BACKUP_KEEP_WEEKS=1
- BACKUP_KEEP_MONTHS=1
- HEALTHCHECK_PORT=8080
networks:
main:
154 changes: 154 additions & 0 deletions roles/vote/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
# Deploy your own Loomio

See: https://github.com/loomio/loomio-deploy/blob/master/README.md

## Network configuration

### DNS Records
To allow people to access the site via your hostname you need an A record:

```
A loomio.example.com, 192.0.2.1
```

Loomio supports "Reply by email" and to enable this you need an MX record so mail servers know where to direct these emails.

```
MX loomio.example.com, loomio.example.com, priority 0
```

Additionally, create two CNAME records that point to `loomio.example.com`.

```
CNAME channels.loomio.example.com, loomio.example.com
CNAME hocuspocus.loomio.example.com, loomio.example.com
```

## Configure the server

### SSL teriminating proxy

By default, docker-compose.yml includes an nginx proxy container that automatically handles fetching an SSL certificate via LetsEncrypt.org. If you don't need SSL termination, or you're running Loomio from behind a proxy, you can safely remove the nginx services from the docker-compose.yml file. The loomio app container will happily speak plain HTTP on port 3000 (by default). Configuring reverse proxies and other advanced configurations are outside the scope of this documentation, but at minimum it's suggested to preserve the HTTP host header and to set X-FORWARDED-PROTO if terminating SSL upstream.

### Setup SMTP

You need to bring your own SMTP server for Loomio to send emails.

If you already have an SMTP server, that's great, put the settings into the `env` file.

For everyone else here are some options to consider:

- Look at the (sometimes free) services offered by [SendGrid](https://sendgrid.com/), [SparkPost](https://www.sparkpost.com/), [Mailgun](http://www.mailgun.com/), [Mailjet](https://www.mailjet.com/pricing).

- Setup your own SMTP server with something like Haraka

Edit the `.env` file and enter the right SMTP settings for your setup.

You might also need to add an SPF DNS record to indicate that the SMTP can send mail for your domain.

### Initialize the database
This command initializes a new database for your Loomio instance to use.

```
docker compose up -d db
docker compose run app rake db:setup
```

### Install crontab
Doing this tells the server what regular tasks it needs to run. These tasks include:

* Noticing which proposals are closing in 24 hours and notifying users.
* Closing proposals and notifying users they have closed.
* Sending "Yesterday on Loomio", a digest of activity users have not already read. This is sent to users at 6am in their local timezone.

Run `crontab -e` and append the following line:

```
0 * * * * /usr/bin/docker exec loomio-worker bundle exec rake loomio:hourly_tasks > ~/rake.log 2>&1
```

## Starting the services
This command starts the database, application, reply-by-email, and live-update services all at once.

```
docker compose up -d
```

Give it a minute to start, then visit your URL while crossing your fingers!

If you visit the url with your browser and the rails server is not yet running, but nginx is, you'll see a "503 bad gateway" error message.

You'll want to see the logs as it all starts, run the following command:

```
docker compose logs -f
```

## Try it out

visit your hostname in your browser.

Once you have signed in (and confirmed your email), grant yourself admin rights

```
docker compose run app rails c
User.last.update(is_admin: true)
```

you can now access the admin interface at https://loomio.example.com/admin


## If something goes wrong

To see system error messages as they happen run `docker compose logs -f` and make a request against the server.

If you want to be notified of system errors you could setup [Sentry](https://sentry.io/) and add it to the env.

Confirm `env` settings are correct.

After you change your `env` files you need to restart the system:

```sh
docker compose down
docker compose up -d
```

To update Loomio to the latest stable version just run the update script.

```sh
./scripts/update
```

To login to your running rails app console:

```sh
docker compose run app rails c
```

A PostgreSQL shell to inspect the database:

```sh
docker exec -ti loomio-db su - postgres -c 'psql loomio_production'
```

## Backups

The default docker-compose.yml includes automatic backups with [prodrigestivill/docker-postgres-backup-local](https://github.com/prodrigestivill/docker-postgres-backup-local), however, you'll need to run `mkdir -p pgdumps && chown -R 999:999 pgdumps` to set the correct permissions for this to work.

You can test that the automatic backup permissions are correct with this command:

```
docker run --rm -v "$PWD:/backups" -u "$(id -u):$(id -g)" --network=loomio-deploy_main -e POSTGRES_HOST=db -e POSTGRES_DB=loomio_production -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=password prodrigestivill/postgres-backup-local /backup.sh
```

However, sometimes you just want to make or restore an SQL snapshot directly.

Dump SQL
```
docker exec -ti loomio-db su - postgres -c 'pg_dump -c loomio_production' > loomio_production.sql
```

Restore SQL
```
cat loomio_production.sql | docker exec -i loomio-db su - postgres -c 'psql loomio_production'
```
5 changes: 5 additions & 0 deletions roles/vote/files/.backup-ignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pgdata*
backups*
.git*
client*
nginx*
21 changes: 21 additions & 0 deletions roles/vote/files/create_backup
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/bin/bash
# run as: scripts/backup_fs .
# this script generates a tgz file with the db dump, user uploads and site config

# first argument when calling the script should be the dir of loomio-deploy
SOURCE_DIR=$1

# this number specifies how many days to retain backups on disk
BACKUP_RETENTION_DAYS=1

BACKUP_DIR=$SOURCE_DIR/backups
DAY_OF_MONTH=`date '+%-d'`
MOD_DAYS=$(($DAY_OF_MONTH % $BACKUP_RETENTION_DAYS))
DEST_FILE=$BACKUP_DIR/`hostname`-$MOD_DAYS.tgz

echo "writing database dump: /pgdumps/loomio_production.dump"
docker exec loomio-db su - postgres -c 'pg_dump -O -Fc loomio_production -f /pgdumps/loomio_production.dump'

echo "writing backup file: $DEST_FILE"
mkdir -p $BACKUP_DIR
tar cvzf $DEST_FILE -X $SOURCE_DIR/.backup-ignore $SOURCE_DIR
2 changes: 2 additions & 0 deletions roles/vote/files/update
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/bash
docker system prune -a -f && docker compose pull && docker compose down && docker compose run app rake db:migrate && docker compose down && docker compose up -d --remove-orphans
Loading