Commit 316d1b08 authored by Pietro Albini's avatar Pietro Albini

initial commit

parents
# Local configuration and stuff
/envs/*.local
/vault-password
# Temporary stuff
/.deploy-ansible-home
# Configurazione dei server di Ubuntu-it
Questo repository contiene la configurazione dei server di Ubuntu-it. La
configurazione è gestita interamente con Ansible.
## Deploy della configurazione
Per effettuare il deploy di alcuni cambiamenti alla configurazione del server,
bisogna modificarla e poi lanciare lo script di deploy:
```
$ ./deploy <ambiente> <playbook>
```
L'ambiente per la macchina di produzione è `prod`, ed è possibile crearne uno
locale. Il playbook è il nome del playbook di ansible che si vuole eseguire
sull'ambiente. Per esempio, per eseguire il playbook `main.yml` in produzione è
necessario digitare il comando:
```
$ ./deploy prod main
```
Potrebbe esser necessario decriptare alcuni file nel repository prima di
eseguire il deploy: vedere la sezione "Ansible Vault" più in basso per maggiori
dettagli.
## Creazione di ambienti locali
È possibile creare ambienti locali, la cui configurazione non è salvata nel
repository git: questi ambienti sono utili per esempio se si vuole provare le
modifiche su un server in locale.
Gli ambienti locali sono identificati dal nome col suffisso `.local`, ma
possono essere usati nel comando senza il suffisso (per esempio, l'ambiente
`dev.local` può essere chiamato come `dev`). Inoltre, è possibile sovrascrivere
ambienti esistenti creando ambienti locali con lo stesso nome.
## Ansible Vault
In questo repository sono salvati dei valori segreti, criptati con Ansible
Vault, ed è necessario decriptarli per poter eseguire alcuni playbook. È
possibile farlo in due modi:
* Puoi inserire la password di Ansible Vault ogni volta che viene richiesta
* Puoi creare uno script eseguibile chiamato `vault-password`, che prende la
password dal tuo password manager (o equivalente) e la mostra a schermo: lo
script verrà chiamato da Ansible in background per ottenere la password
Lo script eseguibile è motlo comodo perché permette di non scrivere la password
ogni volta. Un esempio di script è il seguente:
```bash
#!/bin/bash
pass -c git/uit/ubuntu-it-sistemisti/servers-config/ansible-vault | head -n 1
```
È possibile creare nuovi file criptati e modificarli con il comando
`ansible-vault`.
#!/bin/bash
set -euo pipefail
IFS=$'\n\t'
DIR_PLAYBOOKS="playbooks"
DIR_ENVIRONMENTS="envs"
DIR_ROLES="roles"
DIR_GROUP_VARS="group_vars"
DIR_TEMP=".deploy-ansible-home"
FILE_VAULT_PASSWORD="vault-password"
BIN_ANSIBLE_PLAYBOOK="ansible-playbook"
usage() {
echo "usage: $0 <environment> <playbook>"
exit 1
}
# Load arguments from CLI
if [[ $# -ne 2 ]]; then usage; fi
environment="$1"
playbook="$2"
env="${DIR_ENVIRONMENTS}/${environment}"
playbook_file="${DIR_PLAYBOOKS}/${playbook}.yml"
# Support local environments
# Local environments overrides git ones
if [[ -d "${env}.local" ]]; then
env="${env}.local"
fi
# Validate CLI arguments
if [[ ! -d "${env}" ]]; then
echo "error: environment not found: ${environment}"
echo
echo "available environments:"
for available in `ls "${DIR_ENVIRONMENTS}"`; do
echo " - ${available}"
done
exit 1
fi
if [[ ! -f "${playbook_file}" ]]; then
echo "error: playbook not found: ${playbook}"
echo
echo "available playbooks:"
for available in `ls "${DIR_PLAYBOOKS}"`; do
echo " - `echo "${available}" | sed 's/\.yml$//'`"
done
exit 1
fi
# Create the temporary working directory
rm -rf "${DIR_TEMP}"
mkdir -p "${DIR_TEMP}/play"
ln -s "`readlink -f "${DIR_ROLES}"`" "${DIR_TEMP}/play/roles"
ln -s "`readlink -f "${DIR_GROUP_VARS}"`" "${DIR_TEMP}/play/group_vars"
ln -s "`readlink -f "${playbook_file}"`" "${DIR_TEMP}/play/playbook.yml"
ln -s "`readlink -f "${env}"`" "${DIR_TEMP}/env"
# Get the flags for the ansible-vault password
if [[ -f "${FILE_VAULT_PASSWORD}" ]]; then
vault_flags="--vault-password-file=`readlink -f "${FILE_VAULT_PASSWORD}"`"
else
vault_flags="--ask-vault-pass"
fi
# Finally execute the playbook against the server
"${BIN_ANSIBLE_PLAYBOOK}" -i "${DIR_TEMP}/env/hosts" \
"${DIR_TEMP}/play/playbook.yml" \
${vault_flags} \
|| true
# Remove temporary directory
rm -rf "${DIR_TEMP}"
[roadhouse]
roadhouse.ubuntu-it.org ansible_user=manage
---
##############
# SSH keys #
##############
ssh_keys_pietroalbini: |
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCR+7NAwSC7K7GvHxUgkvNCVAyZrvRA+IXp4C8STBHLcebcM1/sx9HmbrOP471eN4p6xWA3c+1nqxlWs1rWmazRYvEopkaxCSzgRb1B7BsqsUEDABTXHaZW0YqYBjmbmK/kipnNmgfIiwHCLMJ2C2JP2ThG/mbp/NxuPfpECK+23fzMGOHn6hdr3XlZXzCPKuT1sI6kcIHCaqQII72qjDnfb4dgDPOGgiPTGynoi0yc1SiYDK4Qu/NQ3BpxH8GcPPcbPRclyhiWB4uxK2iwHTHM2RZbQvgLbVDSZi1ESMfJAVWqOBbpGMf356J78xUmOM0beWVnyarMiX2i8xZdVQdB yubikey-3811256
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCdVVy/lfTMwDVTDXFJmF/BzI7Rjw3Fu4WkVnkdJnAHcBEZk/hOAoBq26mNzcX3VbLlpSd48UrtR8gEKqmeHwBeMkODgui+XC3TszRxbTVzr0f4bcnSj/XNfptXzbXfyf2h/PxrCrgE5E2JD3O4BAcGr3QGeF6fP7Q9J9pbLIHZVvoiX4/Ll7NLJtQrKa5ssBD4kpYt3HS6Ab25lWvE0PLu4J3VpM29DBmVxp3cBnbENlr9hh2XDhgyKwjkboKiQkK1s1/pfFDOhI4UYVu2g3Jzwxk+KxGgsLxenADtdENZRsinfDFzxrhHmpLhrV+e3pTpvwnEO3AaS/WWdxSgBBYf backup-pietro
ssh_keys_mapreri: |
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC4Zra0f7cwrWmrIDzyhFupShU91/kUZNBLc449vBnGyY51p8/6/yGLwAJfhsrj57b/qy7Z13CwrxO8bxuAYEv3cXADyTVPHa+LuAu7tj5vjmT61/EB2og8qckNotn6MpNT7NvA6mEOtdhcp2shljWoQYhj/fz/tdonNC67z7f8WrIP5DFalNNluy1YSt08NZI+PnsLyAsaKJnD3VlRhMVMBl0txX9o4qbAieDvdZ665ZiRYZlprY9gdXFCSSLlP/rGOYuRt0BRnH+YRddgkvMZLlR3Eh/O0KQipIO/ndl2WxU6ch6Rp9IyMLIsn9rwhlFZE/m4I9b0ejtCetuLh8t8g7ODBzmp3/LekXgo9qu47ov3Jgz3mGFWThV3/As+fKxg+chPvxif1f7tY8VtR+Ug3ma3uVDwa4dnP6q+QKhLkz/ejA/3uvJ65fivBZA351jtlzwOEqcfQouz2fX95yFPLa2QAUCZIgm9zhRffdulvJAhPgLfW3RkXJfU2xAknNV7OOxXsH6kXC9Xv7K8f6cGut1ls4SVvaCHLFrnyI/5B9TmZWPTm577JdjFrT2e0dFmua7wEwT89liJtPil9LZa2M46KKMX+7mp6JAypiKpT9FQbvJ6+yFz6tcwwlEMVeDfJtaQPcapC6mMbPEiirdcq4wrA5ruz4TLGrf2r+Bj9w== mattia@4B043FCDB9444540
ssh_keys_janvitus: |
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDUzuSDyKJeIbGTGk6CeoxBZGGSJMr03O7TScBjzD45E98ejxknQoFqsGeoi6rSo8YuvSHRVO3rhCwpcnIjIkZM0BEAwPilUrxiuIXBMkuu5Rv/0CB8PsVP9kg9XtmJr2PaA0iQKg4ije0CEG5j/pom9QZsaWggCIp+SAoIFys7G1bSRmPLHghBWxpoKtd1pjhbwZJ+e/kAPIWaDZcILvTVqdUn8WpzbA0mqXWdSwXmf2fggx+u0Qj1PEJWJnmQgf3TAlnBfUHcYsjdFp2jnEzM+kFhXqXB17FijZn3Uz5R2VFsLUsX10BxV6frKOi536/KvXlbwhoEwIBtg2aHX7/F gianvito@ubuntubox
---
- hosts: roadhouse
become: yes
become_user: root
roles:
- role: common
# SSH keys allowed to deploy with ansible (user "manage")
management_ssh: |
{{ ssh_keys_pietroalbini }}
{{ ssh_keys_mapreri }}
{{ ssh_keys_janvitus }}
admin_users:
pietroalbini: "{{ ssh_keys_pietroalbini }}"
mapreri: "{{ ssh_keys_mapreri }}"
janvitus: "{{ ssh_keys_janvitus }}"
- role: nginx
[Unit]
Description=Firewall initialization script
After=network.target
[Service]
Type=oneshot
KillMode=none
ExecStart=/usr/local/sbin/firewall
ExecStop=/usr/local/sbin/firewall --reset
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
#!/bin/bash
# Check if ip6tables is supported by the machine
if which ip6tables >/dev/null 2>&1 && /sbin/ip6tables -L >/dev/null 2>&1; then
IPv6=true
COMMANDS=( "/sbin/iptables" "/sbin/ip6tables" )
echo "Operating on the following protocols: ipv4, ipv6"
else
IPv6=false
COMMANDS=( "/sbin/iptables" )
echo "Operating on the following protocols: ipv4"
fi
CHAINS=( "tcp_bad" "public_input_tcp" "public_input_udp" "public_input_icmp"
"input" )
PUBLIC_IFACE="eth0"
LOCAL_IFACE="lo"
# Execute a command on all iptables commands
command() {
for cmd in "${COMMANDS[@]}"; do
"${cmd}" $@
done
}
command4() {
"/sbin/iptables" $@
}
command6() {
if "${IPv6}"; then
"/sbin/ip6tables" $@
fi
}
# Parse arguments
only_reset=false
for arg; do
if [[ "${arg}" == "-r" ]] || [[ "${arg}" == "--reset" ]]; then
only_reset=true
fi
done
# Reset the firewall
command -D INPUT -j input 2>/dev/null # Remove firewall's input chain
# Flush chains
for chain in "${CHAINS[@]}"; do
command -F "${chain}" 2>/dev/null
done
# Delete chains -- must be done after because of references
for chain in "${CHAINS[@]}"; do
command -X "${chain}" 2>/dev/null
done
echo "Existing firewall configuration cleaned up"
# If you want only to reset the firewall, don't re-create rules and clear
# policies
if "${only_reset}"; then
command -P INPUT ACCEPT
command -P OUTPUT ACCEPT
command -P FORWARD ACCEPT
echo "Firewall successifully disabled"
exit
fi
# Setup policies
command -P INPUT ACCEPT
command -P OUTPUT ACCEPT
command -P FORWARD DROP
# Create chains
for chain in "${CHAINS[@]}"; do
command -N "${chain}"
done
# Setup bad tcp packets chain
command -A tcp_bad -p tcp --tcp-flags SYN,ACK SYN,ACK -m state --state NEW \
-j REJECT --reject-with tcp-reset
command -A tcp_bad -p tcp ! --syn -m state --state NEW -j DROP
# Setup tcp public input chain
command -A public_input_tcp -j tcp_bad
command -A public_input_tcp -p tcp --dport 22 -j ACCEPT # sshd
# Setup icmp public input chain
command -A public_input_icmp -j ACCEPT
# Setup input chain
command -A input -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
command -A input -i "${LOCAL_IFACE}" -j ACCEPT # Accept localhost connections
command -A input -i "${PUBLIC_IFACE}" -p tcp -j public_input_tcp
command -A input -i "${PUBLIC_IFACE}" -p udp -j public_input_udp
command4 -A input -i "${PUBLIC_IFACE}" -p icmp -j public_input_icmp
command6 -A input -i "${PUBLIC_IFACE}" -p ipv6-icmp -j public_input_icmp
command -A input -j DROP
echo "Applied basic configuration to the firewall"
# Load other config files
for file in /usr/local/share/firewall.d/*.sh; do
if [[ -x "${file}" ]]; then
echo "Loading script ${file}"
source "${file}"
fi
done
# Setup INPUT chain
command -A INPUT -j input # Move to my input chain
echo "Firewall successifully enabled"
Port 22
ListenAddress ::
ListenAddress 0.0.0.0
Protocol 2
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_dsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
UsePrivilegeSeparation yes
KeyRegenerationInterval 3600
ServerKeyBits 1024
SyslogFacility AUTH
LogLevel INFO
UsePAM yes
LoginGraceTime 120
StrictModes yes
PermitRootLogin no
PermitEmptyPasswords no
PasswordAuthentication no
RSAAuthentication yes
PubkeyAuthentication yes
ChallengeResponseAuthentication no
IgnoreRhosts yes
RhostsRSAAuthentication no
HostbasedAuthentication no
X11Forwarding no
PrintMotd no
PrintLastLog yes
TCPKeepAlive yes
AcceptEnv LANG LC_*
Subsystem sftp /usr/lib/openssh/sftp-server
AllowGroups allow-ssh
# Allow the passwordless-sudo group to use sudo without password
%passwordless-sudo ALL=(ALL:ALL) NOPASSWD:ALL
---
- name: common.reload-ssh
service:
name: ssh
state: restarted
- name: common.reload-firewall
service:
name: firewall
state: restarted
- name: common.reload-systemd
shell: systemctl daemon-reload
---
- name: update apt cache
apt:
update_cache: true
cache_valid_time: 300
- name: install basic packages
apt:
name: "{{ item }}"
state: present
with_items:
- python
- vim
- openssh-server
- iptables
---
- name: create backup user
user:
name: local-backup
state: present
system: true
createhome: false
- name: create local-backup home
file:
name: "/var/local/local-backup-home/{{ item }}"
state: directory
mode: 0700
owner: local-backup
group: local-backup
with_items:
- ""
- .ssh
- name: set local-backup home
user:
name: local-backup
home: /var/local/local-backup-home
- name: create backup config dir
file:
path: /usr/local/share/backup.d
state: directory
mode: 0750
owner: root
group: local-backup
---
- name: remove unwanted users
user:
name: "{{ item }}"
state: absent
with_items:
- ubuntu # default user
- name: remove unwanted paths
file:
name: "{{ item }}"
state: absent
with_items:
- /home/ubuntu # home of the ubuntu user
- /etc/sudoers.d/90-cloud-init-users # sudo for the ubuntu user
---
- name: create the firewall config dir
file:
path: /usr/local/share/firewall.d
mode: 0700
state: directory
- name: upload firewall script
copy:
src: firewall/firewall.sh
dest: /usr/local/sbin/firewall
mode: 0700
notify:
- common.reload-firewall
- name: upload firewall service
copy:
src: firewall/firewall.service
dest: /etc/systemd/system/firewall.service
notify:
- common.reload-systemd
- common.reload-firewall
- name: enable firewall.service
service:
name: firewall
enabled: yes
---
- name: apt
include: apt.yml
- name: users
include: users.yml
- name: ssh
include: ssh.yml
- name: firewall
include: firewall.yml
- name: backup
include: backup.yml
- name: cleanup
include: cleanup.yml
---
- name: copy ssh configuration
copy:
src: ssh/sshd_config
dest: /etc/ssh/sshd_config
mode: 0644
notify: common.reload-ssh
---
- name: create groups
group:
name: "{{ item }}"
state: present
with_items:
- allow-ssh
- passwordless-sudo
- name: create user manage
user:
name: manage
groups: allow-ssh,passwordless-sudo
state: present
shell: /bin/bash
- name: set ssh keys for manage
authorized_key:
user: manage
key: "{{ management_ssh }}"
exclusive: true
state: present
- name: create admin users
user:
name: "{{ item }}"
groups: allow-ssh,passwordless-sudo,systemd-journal
state: present
shell: /bin/bash
with_items: "{{ admin_users.keys() }}"
- name: register admin users as a fact
set_fact:
facts_common_admin_users: "{{ admin_users.keys() }}"
- name: set ssh keys for admin users
authorized_key:
user: "{{ item }}"
key: "{{ admin_users[item] }}"
exclusive: true
state: present
with_items: "{{ admin_users.keys() }}"
- name: allow passwordless-sudo to use sudo
copy:
src: users/sudoers-passwordless-sudo
dest: /etc/sudoers.d/passwordless-sudo
mode: 0440
---
- name: web-server.reload-nginx
service:
name: nginx
state: reloaded
---
- name: setup
include: setup.yml
---
- name: install nginx
apt:
name: "{{ item }}"
state: present
with_items:
- nginx
- name: create directories for nginx
file:
path: "/etc/nginx/{{ item }}"
state: directory
mode: 0755
with_items:
- sites
- name: remove unused nginx directories
file:
path: "{{ item }}"
state: absent
with_items:
- /var/www/html
- /etc/nginx/sites-available
- /etc/nginx/sites-enabled
- name: upload nginx configuration files
template:
src: "config/{{ item }}"
dest: "/etc/nginx/{{ item }}"
mode: 0644
with_items:
- nginx.conf
- conf.d/default-site.conf
- conf.d/optimize.conf
notify:
- web-server.reload-nginx
- name: allow http through the firewall
template:
src: firewall.sh
dest: /usr/local/share/firewall.d/web-server.sh
mode: 0700
notify:
- common.reload-firewall
server {
listen 80 default;
listen [::]:80 default;
location / {
return 404;
}
}
######################
# gzip compression #
######################
gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_comp_level 6;
gzip_min_length 300;
gzip_buffers 16 8k;
gzip_proxied any;
gzip_types
text/plain
text/js
text/xml
text/javascript
application/javascript
application/x-javascript
application/json
application/xml
application/xml+rss;
user www-data;
worker_processes auto;
pid /run/nginx.pid;
events {
worker_connections 768;
}
http {
####################
# Basic Settings #
####################
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
server_tokens off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
#######################
# SSL configuration #
#######################
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
########################
# Logs configuration #
########################
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
#########################
# Extra configuration #
#########################
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites/*;
}
# Allow incoming requests on port 80
command -A public_input_tcp -p tcp --dport 80 -j ACCEPT
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment