Skip to content

Commit cf66ff9

Browse files
committed
First commit
0 parents  commit cf66ff9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+1500
-0
lines changed

.env.example

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
TARGET_DOMAIN=
2+
DIGITALOCEAN_ACCESS_TOKEN=dop_v1_
3+
SPACES_ACCESS_TOKEN=
4+
SPACES_SECRET_KEY=
5+
SSH_HOST_KEY=id_rsa

.gitignore

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Env
2+
.env
3+
4+
# Editors
5+
.idea
6+
7+
# Terraform
8+
**/.terraform/
9+
.tmp/*/*
10+
!.tmp/.gitkeep
11+
!.tmp/*/.gitkeep
12+
.infracost
13+
*.tmp
14+
15+
# AWS
16+
.aws/*
17+
!.aws/.gitkeep

Dockerfile

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# syntax=docker/dockerfile:1
2+
FROM ubuntu:21.10 as base
3+
RUN apt update -y
4+
5+
FROM base as dowloader
6+
7+
RUN apt install curl unzip tar gzip git ca-certificates openssh-client -y
8+
9+
# Terraform download
10+
ARG TERRAFORM_VER
11+
RUN cd /tmp && \
12+
curl https://releases.hashicorp.com/terraform/${TERRAFORM_VER}/terraform_${TERRAFORM_VER}_linux_amd64.zip --output terraform.zip && \
13+
unzip terraform.zip && \
14+
mv terraform /usr/bin/ && \
15+
rm -rf /tmp/* && \
16+
terraform --version
17+
18+
ARG PACKER_VER
19+
RUN cd /tmp && \
20+
curl https://releases.hashicorp.com/packer/${PACKER_VER}/packer_${PACKER_VER}_linux_amd64.zip --output packer.zip && \
21+
unzip packer.zip && \
22+
mv packer /usr/bin/ && \
23+
rm -rf /tmp/* && \
24+
packer version
25+
26+
ARG DOCTL_VER
27+
RUN cd /tmp && \
28+
curl -L https://github.com/digitalocean/doctl/releases/download/v${DOCTL_VER}/doctl-${DOCTL_VER}-linux-amd64.tar.gz --output doctl.tar.gz && \
29+
ls -la /tmp && \
30+
tar xf doctl.tar.gz -C /tmp && \
31+
mv /tmp/doctl /usr/bin/doctl && \
32+
rm -rf /tmp/* && \
33+
doctl version
34+
35+
# Install task (https://taskfile.dev)
36+
RUN sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d -b /usr/bin \
37+
&& task --version
38+
39+
# Generate private key
40+
RUN ssh-keygen -q -t rsa -N '' -f /root/.ssh/id_rsa
41+
42+
# Target
43+
FROM base
44+
45+
# configure nodejs repository
46+
RUN curl -fsSL https://deb.nodesource.com/setup_16.x | bash -
47+
RUN apt install ca-certificates ssh nodejs ansible -y
48+
49+
# Workdir
50+
RUN mkdir -p /project
51+
WORKDIR /project
52+
53+
# Terraform cache
54+
ENV TF_PLUGIN_CACHE_DIR=/project/.tmp/.terraform.d/plugin-cache
55+
ENV PACKER_CONFIG_DIR=/project/.tmp/
56+
# ENV PACKER_CACHE_DIR=/project/.tmp/.packer.d
57+
58+
# Bash improviments
59+
RUN echo "alias ll='ls -l'" >> /root/.bashrc && \
60+
echo "complete -C /usr/bin/terraform terraform" >> /root/.bashrc && \
61+
echo 'PS1="\n\[\e[0;31m\]┌─[\[\e[0m\]\[\e[1;33m\]\u\[\e[0m\] ܁\[\e[1;36m\]\[\e[0m\]\[\e[1;34m\]\w\[\e[0m\]\[\e[0;31m\]]\n\[\e[0;31m\]└─\e[0;31m\]$ \[\e[0m\]"' >> /root/.bashrc
62+
63+
# Copy from downloader stage
64+
COPY --from=dowloader --chown=root:root /root/.ssh/ /root/.ssh/
65+
COPY --from=dowloader --chown=root:root /usr/bin/terraform /usr/bin/terraform
66+
COPY --from=dowloader --chown=root:root /usr/bin/packer /usr/bin/packer
67+
COPY --from=dowloader --chown=root:root /usr/bin/doctl /usr/bin/doctl
68+
COPY --from=dowloader --chown=root:root /usr/bin/task /usr/bin/task
69+
70+
# prepare ssh
71+
RUN chmod 600 /root/.ssh/id_rsa && \
72+
ssh-keyscan -H github.com >> /root/.ssh/known_hosts && \
73+
ssh-keyscan -H bitbucket.com >> /root/.ssh/known_hosts && \
74+
echo "StrictHostKeyChecking no" >> /root/.ssh/ssh_config
75+
76+
COPY docker-entrypoint.sh /docker-entrypoint.sh
77+
78+
RUN chmod 600 /docker-entrypoint.sh && \
79+
chmod +x /docker-entrypoint.sh
80+
81+
ENTRYPOINT ["/docker-entrypoint.sh"]
82+
CMD ["bash"]

README.md

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# LibreCode - Discourse
2+
3+
Esta infra é construída com [Packer](https://www.packer.io/), [Terraform](https://www.terraform.io/) e [Ansible](https://docs.ansible.com/)
4+
5+
Terraform e Packer se comunicam com a [DigitalOcean](https://www.digitalocean.com/) para construir toda a infra necessária.
6+
7+
Packer é o responsável por criar a imagem base que será usada nas máquinas que vão rodar os serviços.
8+
9+
O Terraform usa a imagem base para subir as máquinas (vazias)
10+
11+
Ansible é o responsável por provisionar a aplicação nos servidores criados pelo terraform.
12+
13+
Para mais informações, consulte as subpastas deste projeto.
14+
15+
- [packer](packer/README.md)
16+
- [terraform](terraform/README.md)
17+
- [ansible](ansible/README.md)
18+
19+
## Requisitos
20+
21+
- [Docker ~v20.10](https://docs.docker.com/engine/install/)
22+
- [Docker Compose ~v2.3](https://docs.docker.com/compose/cli-command/)
23+
24+
## Comandos
25+
26+
Todas as dependencias necessárias para trabalhar com a infra estão dentro do [`Dockerfile`](Dockerfile) deste projeto.
27+
28+
Basta construir a imagem e executar o container com os comandos abaixo.
29+
30+
> Lembre-se de gerar suas credenciais da DigitalOcean e criar o arquivo `.env` com base no `.env.example`
31+
32+
```sh
33+
docker-compose build
34+
docker-compose run tooling
35+
```

ansible/.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
inventory.*.ini
2+
.vault.*

ansible/README.md

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Ansible
2+
3+
Automatiza o processo de provisionamento das aplicações.
4+
5+
O processo de provisionamento consiste em gerar um `docker-compose.yml` no servidor do serviço e um arquivo de definição do [NGINX](https://www.nginx.com/) para fazer [proxy reverso](https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/) para o serviço gerenciado pelo [docker-compose](https://docs.docker.com/compose/).
6+
7+
> Para mais informações sobre o NGINX e Docker instalados no servidor, consultar o [packer](../packer/README.md).
8+
9+
## Comandos
10+
11+
> Este projeto usa o utilitário [`taskfile`](https://taskfile.dev/) para simplificar algumas ações.
12+
13+
Sempre antes de fazer um deploy atualize o inventário.
14+
15+
```sh
16+
task inventory
17+
```
18+
Também é possivel encadear comandos.
19+
20+
```sh
21+
task inventory deploy:discourse
22+
```
23+
24+
Para conhecer os comandos disponíveis use o opção `--list`
25+
26+
```sh
27+
task --list
28+
```
29+
30+
## Secredos
31+
32+
Este projeto usa [ansible-vault](https://docs.ansible.com/ansible/latest/user_guide/vault.html) para proteger as alguns valores secretos.
33+
34+
A senha fica no arquivo `.vault.pass.txt`, este arquivo nunca pode ser versionado.
35+
36+
```sh
37+
ansible-vault encrypt vars/.secrets.$ENV.yml
38+
```
39+
40+
## Primeiro deploy
41+
42+
O primeiro deploy vai demorar alguns minutos, pois todas as *migrations* e *builds* serão executados neste momento.

ansible/Taskfile.yaml

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# https://taskfile.dev
2+
3+
version: '3'
4+
5+
vars:
6+
STAGE: development
7+
8+
tasks:
9+
secret:view:
10+
desc: Exibe o conteúdo do arquivo de segredos
11+
cmds:
12+
- ansible-vault view vars/.secrets.{{ .STAGE }}.yml
13+
14+
secret:edit:
15+
desc: Edita o conteúdo do arquivo de segredos
16+
cmds:
17+
- ansible-vault edit vars/.secrets.{{ .STAGE }}.yml
18+
19+
inventory:
20+
desc: Gera o arquivo de inventário do ansible
21+
cmds:
22+
- NODE_ENV={{ .STAGE }} node scripts/generate-inventary.mjs > inventory.{{ .STAGE }}.ini
23+
24+
deploy:discourse:
25+
desc: faz deploy do e-Cidade discourse
26+
cmds:
27+
- |
28+
ansible-playbook discourse.yml -v \
29+
--inventory-file inventory.{{ .STAGE }}.ini \
30+
--extra-vars "@vars/{{ .STAGE }}.yml" \
31+
--extra-vars "@vars/.secrets.{{ .STAGE }}.yml" {{.CLI_ARGS}}

ansible/ansible.cfg

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[defaults]
2+
; callbacks_enabled = timer, profile_tasks, profile_roles
3+
interpreter_python = /usr/bin/python3
4+
forks=50
5+
pipelining = True
6+
vault_password_file = ./.vault.pass.txt
7+
host_key_checking = False
8+
callbacks_enabled = timer
9+
10+
[ssh_connection]
11+
ssh_args = -o ControlMaster=auto -o ControlPersist=60s

ansible/discourse.yml

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#!/usr/bin/env ansible-playbook
2+
3+
- name: 'deploy e-cidade discourse'
4+
hosts: all
5+
become: true
6+
gather_facts: false
7+
strategy: free
8+
roles:
9+
- role: discourse
10+
vars:
11+
DISCOURSE_HOST: "{{ lookup('ansible.builtin.env', 'TARGET_DOMAIN') }}"
12+
DISCOURSE_DOCKER_IMAGE: docker.io/bitnami/discourse:2.8.6
13+
REDIS_DOCKER_IMAGE: docker.io/bitnami/redis:6.2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
# defaults file for ansible
3+
4+
database_host:
5+
database_user:
6+
database_name:
7+
database_port:
8+
database_sslmode: require
9+
EXPOSE_PORT: 8073
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Files
2+
3+
Os arquivos `.crt` devem ser obtidos na DigitalOcean.
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
- name: start docker-compose
2+
community.docker.docker_compose:
3+
project_name: "discourse"
4+
files: docker-compose.discourse.yml
5+
project_src: /app
6+
state: present
7+
remove_orphans: true
8+
pull: true
9+
10+
- name: restart nginx
11+
ansible.builtin.service:
12+
name: nginx
13+
state: restarted
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
- name: Generate database-ca-certificate.crt
2+
ansible.builtin.copy:
3+
src: files/{{ ENVIRONMENT }}--database-ca-certificate.crt
4+
dest: /app/database-ca-certificate.crt
5+
force: no
6+
tags:
7+
- database
+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
- name: Generate docker-compose.yml
2+
ansible.builtin.template:
3+
src: templates/docker-compose.yml.j2
4+
dest: /app/docker-compose.discourse.yml
5+
notify: start docker-compose
6+
tags:
7+
- docker
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
- import_tasks: ca-certificate.yml
2+
- import_tasks: docker.yml
3+
- import_tasks: nginx.yml
+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
- name: Generate nginx config
2+
ansible.builtin.template:
3+
src: templates/nginx.conf.j2
4+
dest: /etc/nginx/sites-enabled/discourse
5+
backup: no
6+
notify: restart nginx
7+
tags:
8+
- nginx
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# refs:
2+
# - https://github.com/discourse/discourse/blob/v2.8.3/config/discourse_defaults.conf
3+
# - https://github.com/bitnami/bitnami-docker-discourse/blob/master/2/debian-10/rootfs/opt/bitnami/scripts/discourse-env.sh
4+
5+
x-common-env: &common-env
6+
# ALLOW_EMPTY_PASSWORD is recommended only for development.
7+
ALLOW_EMPTY_PASSWORD: "yes"
8+
BITNAMI_DEBUG: "yes"
9+
DISCOURSE_SITE_NAME: e-Cidade
10+
DISCOURSE_PRECOMPILE_ASSETS: 1
11+
12+
LC_ALL: pt_BR.UTF-8
13+
LANG: pt_BR.UTF-8
14+
LANGUAGE: pt_BR.UTF-8
15+
DISCOURSE_DEFAULT_LOCALE: pt_BR
16+
17+
DISCOURSE_HOST: {{ DISCOURSE_HOST }}
18+
DISCOURSE_DATABASE_HOST: {{ database_host }}
19+
DISCOURSE_DATABASE_PASSWORD: {{ secrets.database_password }}
20+
DISCOURSE_DATABASE_PORT_NUMBER: {{ database_port }}
21+
DISCOURSE_DATABASE_SSLMODE: {{ database_sslmode }}
22+
DISCOURSE_DATABASE_USER: {{ database_user }}
23+
DISCOURSE_DATABASE_NAME: {{ database_name }}
24+
DISCOURSE_REDIS_HOST: redis
25+
DISCOURSE_REDIS_PORT_NUMBER: 6379
26+
27+
{#
28+
DISCOURSE_SMTP_ADDRESS: {{ secrets.email_smtp_address }}
29+
DISCOURSE_SMTP_PORT: {{ secrets.email_smtp_port }}
30+
DISCOURSE_SMTP_USER_NAME: {{ secrets.email_smtp_user_name }}
31+
DISCOURSE_SMTP_PASSWORD: "{{ secrets.email_smtp_password }}"
32+
#DISCOURSE_SMTP_ENABLE_START_TLS: true # (optional, default true)
33+
DISCOURSE_SMTP_DOMAIN: {{ hostname }}
34+
DISCOURSE_NOTIFICATION_EMAIL: noreply@{{ hostname }}
35+
#}
36+
37+
version: '3.7'
38+
services:
39+
redis:
40+
image: docker.io/bitnami/redis:6.0
41+
restart: on-failure
42+
environment:
43+
# ALLOW_EMPTY_PASSWORD is recommended only for development.
44+
- ALLOW_EMPTY_PASSWORD=yes
45+
volumes:
46+
- 'redis_data:/bitnami/redis'
47+
48+
discourse:
49+
image: {{ DISCOURSE_DOCKER_IMAGE }}
50+
restart: on-failure
51+
ports:
52+
- '{{ EXPOSE_PORT }}:3000'
53+
volumes:
54+
- 'discourse_data:/bitnami/discourse'
55+
depends_on:
56+
- redis
57+
environment:
58+
<<: *common-env
59+
60+
sidekiq:
61+
image: {{ DISCOURSE_DOCKER_IMAGE }}
62+
restart: on-failure
63+
depends_on:
64+
- discourse
65+
volumes:
66+
- 'sidekiq_data:/bitnami/discourse'
67+
command: /opt/bitnami/scripts/discourse-sidekiq/run.sh
68+
environment:
69+
<<: *common-env
70+
71+
volumes:
72+
redis_data:
73+
driver: local
74+
discourse_data:
75+
driver: local
76+
sidekiq_data:
77+
driver: local

0 commit comments

Comments
 (0)