From 19ebda26b4adb68e14ac9a206d1275a4b7a27c51 Mon Sep 17 00:00:00 2001 From: Waffles Date: Wed, 21 Dec 2022 22:30:01 -0800 Subject: [PATCH] Initial commit --- .gitignore | 1 + .gitmodules | 6 + Makefile | 3 + ansible-role-oh-my-zsh | 1 + ansible.cfg | 3 + frontend.yml | 15 + group_vars/all | 3 + hosts | 27 ++ mastodon.yml | 6 + mta.yml | 22 + roles/ansible-role-neovim | 1 + roles/ansible-role-oh-my-zsh | 1 + roles/frontend/meta/main.yml | 4 + roles/frontend/tasks/main.yml | 55 +++ roles/frontend/templates/cloudflare | 29 ++ roles/frontend/templates/dmca | 4 + roles/frontend/templates/files.j2 | 90 ++++ roles/frontend/templates/mastodon.j2 | 117 +++++ roles/frontend/templates/status | 19 + roles/frontend/templates/tusky | 76 ++++ roles/frontend/templates/waffles | 57 +++ roles/frontend/vars/main.yml | 1 + roles/mastodon/meta/main.yml | 4 + roles/mastodon/tasks/main.yml | 32 ++ roles/mastodon/tasks/repo.yml | 7 + roles/mastodon/tasks/swap.yml | 36 ++ .../docker-compose.sidekiq-default.yml.j2 | 20 + .../docker-compose.sidekiq-ingress.yml.j2 | 19 + .../docker-compose.sidekiq-mailers.yml.j2 | 20 + .../docker-compose.sidekiq-pushpull.yml.j2 | 19 + .../docker-compose.sidekiq-scheduler.yml.j2 | 19 + .../templates/docker-compose.sidekiq.yml.j2 | 15 + .../mastodon/templates/docker-compose.yml.j2 | 33 ++ roles/mastodon/templates/env.production.j2 | 3 + .../mastodon/templates/statsd-mapping.yaml.j2 | 96 +++++ roles/sidekiq/meta/main.yml | 3 + roles/sidekiq/tasks/main.yml | 6 + .../templates/docker-compose.override.yml.j2 | 23 + roles/webapp/meta/main.yml | 4 + roles/webapp/tasks/main.yml | 6 + .../templates/docker-compose.override.yml.j2 | 38 ++ roles/yttrx/meta/main.yml | 12 + roles/yttrx/tasks/main.yml | 27 ++ sidekiq.yml | 20 + templates/nvim/init.vim.j2 | 408 ++++++++++++++++++ webapp.yml | 12 + yttrx.yml | 6 + 47 files changed, 1429 insertions(+) create mode 100644 .gitignore create mode 100644 .gitmodules create mode 100644 Makefile create mode 160000 ansible-role-oh-my-zsh create mode 100644 ansible.cfg create mode 100644 frontend.yml create mode 100644 group_vars/all create mode 100644 hosts create mode 100644 mastodon.yml create mode 100644 mta.yml create mode 160000 roles/ansible-role-neovim create mode 160000 roles/ansible-role-oh-my-zsh create mode 100644 roles/frontend/meta/main.yml create mode 100644 roles/frontend/tasks/main.yml create mode 100644 roles/frontend/templates/cloudflare create mode 100644 roles/frontend/templates/dmca create mode 100644 roles/frontend/templates/files.j2 create mode 100644 roles/frontend/templates/mastodon.j2 create mode 100644 roles/frontend/templates/status create mode 100644 roles/frontend/templates/tusky create mode 100644 roles/frontend/templates/waffles create mode 100644 roles/frontend/vars/main.yml create mode 100644 roles/mastodon/meta/main.yml create mode 100644 roles/mastodon/tasks/main.yml create mode 100644 roles/mastodon/tasks/repo.yml create mode 100644 roles/mastodon/tasks/swap.yml create mode 100644 roles/mastodon/templates/docker-compose.sidekiq-default.yml.j2 create mode 100644 roles/mastodon/templates/docker-compose.sidekiq-ingress.yml.j2 create mode 100644 roles/mastodon/templates/docker-compose.sidekiq-mailers.yml.j2 create mode 100644 roles/mastodon/templates/docker-compose.sidekiq-pushpull.yml.j2 create mode 100644 roles/mastodon/templates/docker-compose.sidekiq-scheduler.yml.j2 create mode 100644 roles/mastodon/templates/docker-compose.sidekiq.yml.j2 create mode 100644 roles/mastodon/templates/docker-compose.yml.j2 create mode 100644 roles/mastodon/templates/env.production.j2 create mode 100644 roles/mastodon/templates/statsd-mapping.yaml.j2 create mode 100644 roles/sidekiq/meta/main.yml create mode 100644 roles/sidekiq/tasks/main.yml create mode 100644 roles/sidekiq/templates/docker-compose.override.yml.j2 create mode 100644 roles/webapp/meta/main.yml create mode 100644 roles/webapp/tasks/main.yml create mode 100644 roles/webapp/templates/docker-compose.override.yml.j2 create mode 100644 roles/yttrx/meta/main.yml create mode 100644 roles/yttrx/tasks/main.yml create mode 100644 sidekiq.yml create mode 100644 templates/nvim/init.vim.j2 create mode 100644 webapp.yml create mode 100644 yttrx.yml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..96934b1 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +roles/mastodon/vars/main.yml diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..43d3e39 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "roles/ansible-role-oh-my-zsh"] + path = roles/ansible-role-oh-my-zsh + url = https://github.com/gantsign/ansible-role-oh-my-zsh.git +[submodule "roles/ansible-role-neovim"] + path = roles/ansible-role-neovim + url = https://github.com/gikeymarcia/ansible-role-neovim.git diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..df19d37 --- /dev/null +++ b/Makefile @@ -0,0 +1,3 @@ +install: + ansible-galaxy install geerlingguy.docker geerlingguy.nginx geerlingguy.certbot + git submodule update --init --recursive diff --git a/ansible-role-oh-my-zsh b/ansible-role-oh-my-zsh new file mode 160000 index 0000000..953875c --- /dev/null +++ b/ansible-role-oh-my-zsh @@ -0,0 +1 @@ +Subproject commit 953875c90d929e68291abc9b11883d32c562f4ab diff --git a/ansible.cfg b/ansible.cfg new file mode 100644 index 0000000..a1e3f70 --- /dev/null +++ b/ansible.cfg @@ -0,0 +1,3 @@ +[defaults] +inventory=./hosts +ansible_connection=paramiko diff --git a/frontend.yml b/frontend.yml new file mode 100644 index 0000000..aa8fd44 --- /dev/null +++ b/frontend.yml @@ -0,0 +1,15 @@ +--- +- name: Configure yttrx frontend environment + hosts: [frontend] + roles: + - role: frontend + vars: + webapp_hosts: + - tusky.masto.yttrx.com + + handlers: + - name: Re-up docker containers + command: docker-compose up -d + args: + chdir: /home/mastodon/live + listen: "docker-compose up" diff --git a/group_vars/all b/group_vars/all new file mode 100644 index 0000000..2f74ec7 --- /dev/null +++ b/group_vars/all @@ -0,0 +1,3 @@ +MASTODON_VERSION: v4.0.2 +REAL_DB_HOST: tusky.masto.yttrx.com +DB_POOL: 25 diff --git a/hosts b/hosts new file mode 100644 index 0000000..bbeeec5 --- /dev/null +++ b/hosts @@ -0,0 +1,27 @@ +[yttrx] +grafana.yttrx.com ansible_user=root +tusky.masto.yttrx.com ansible_user=root +mammut.masto.yttrx.com ansible_user=root +mail.yttrx.com ansible_user=root + +[mastodon] +#tusky.masto.yttrx.com ansible_user=root +mammut.masto.yttrx.com ansible_user=root + +[sidekiq] +wooly.masto.yttrx.com ansible_user=root + +[frontend] +wooly.masto.yttrx.com ansible_user=root + +[webapp] +#wooly.masto.yttrx.com ansible_user=root + +[yttrx:vars] +ansible_python_interpreter=/usr/bin/python3 + +[mta] +mail.yttrx.com ansible_user=root + +[mta:vars] +ansible_python_interpreter=/usr/bin/python3 diff --git a/mastodon.yml b/mastodon.yml new file mode 100644 index 0000000..b76da8a --- /dev/null +++ b/mastodon.yml @@ -0,0 +1,6 @@ +--- +- name: Configure yttrx mastodon environment + hosts: [mastodon] + roles: + - role: mastodon + diff --git a/mta.yml b/mta.yml new file mode 100644 index 0000000..1556692 --- /dev/null +++ b/mta.yml @@ -0,0 +1,22 @@ +--- +- name: Configure yttrx mail server environment + hosts: [mta] + roles: + - role: mta + + handlers: + - name: Restart dovecot + service: + name: dovecot + state: restarted + listen: "restart services" + + - name: Restart postfix + service: + name: postfix + state: restarted + listen: "restart services" + + - name: postmap + command: /usr/sbin/postmap /etc/postfix/virtual + listen: "postmap" diff --git a/roles/ansible-role-neovim b/roles/ansible-role-neovim new file mode 160000 index 0000000..0bc0fc0 --- /dev/null +++ b/roles/ansible-role-neovim @@ -0,0 +1 @@ +Subproject commit 0bc0fc00f1402b5093efe6746655ae73ade60c0d diff --git a/roles/ansible-role-oh-my-zsh b/roles/ansible-role-oh-my-zsh new file mode 160000 index 0000000..953875c --- /dev/null +++ b/roles/ansible-role-oh-my-zsh @@ -0,0 +1 @@ +Subproject commit 953875c90d929e68291abc9b11883d32c562f4ab diff --git a/roles/frontend/meta/main.yml b/roles/frontend/meta/main.yml new file mode 100644 index 0000000..19bd79a --- /dev/null +++ b/roles/frontend/meta/main.yml @@ -0,0 +1,4 @@ +--- +dependencies: + - role: geerlingguy.nginx + - role: mastodon # Required for the www root for nginx diff --git a/roles/frontend/tasks/main.yml b/roles/frontend/tasks/main.yml new file mode 100644 index 0000000..9b90521 --- /dev/null +++ b/roles/frontend/tasks/main.yml @@ -0,0 +1,55 @@ +--- +# Install the requires nginx sites-available + +- name: Create nginx cache dir + file: + path: /data/nginx/cache + state: directory + owner: www-data + group: www-data + +- name: Install nginx site files + template: + src: files.j2 + dest: /etc/nginx/sites-available/files + notify: restart nginx + +- name: Install nginx mastodon config + template: + src: mastodon.j2 + dest: /etc/nginx/sites-available/mastodon + notify: restart nginx + +- name: Enable files + file: + src: /etc/nginx/sites-available/files + dest: /etc/nginx/sites-enabled/files + state: link + +- name: Enable mastodon + file: + src: /etc/nginx/sites-available/mastodon + dest: /etc/nginx/sites-enabled/mastodon + state: link + +- name: Disable default + file: + path: /etc/nginx/sites-enabled/default + state: absent + +- name: Copy dmca + template: + src: dmca + dest: /etc/nginx/dmca + notify: restart nginx + +- name: Copy cloudflare + template: + src: cloudflare + dest: /etc/nginx/cloudflare + notify: restart nginx + +- name: install certbot + package: + name: python3-certbot-nginx + state: present diff --git a/roles/frontend/templates/cloudflare b/roles/frontend/templates/cloudflare new file mode 100644 index 0000000..0bfb71f --- /dev/null +++ b/roles/frontend/templates/cloudflare @@ -0,0 +1,29 @@ +#Cloudflare + +# - IPv4 +set_real_ip_from 173.245.48.0/20; +set_real_ip_from 103.21.244.0/22; +set_real_ip_from 103.22.200.0/22; +set_real_ip_from 103.31.4.0/22; +set_real_ip_from 141.101.64.0/18; +set_real_ip_from 108.162.192.0/18; +set_real_ip_from 190.93.240.0/20; +set_real_ip_from 188.114.96.0/20; +set_real_ip_from 197.234.240.0/22; +set_real_ip_from 198.41.128.0/17; +set_real_ip_from 162.158.0.0/15; +set_real_ip_from 104.16.0.0/13; +set_real_ip_from 104.24.0.0/14; +set_real_ip_from 172.64.0.0/13; +set_real_ip_from 131.0.72.0/22; + +# - IPv6 +set_real_ip_from 2400:cb00::/32; +set_real_ip_from 2606:4700::/32; +set_real_ip_from 2803:f800::/32; +set_real_ip_from 2405:b500::/32; +set_real_ip_from 2405:8100::/32; +set_real_ip_from 2a06:98c0::/29; +set_real_ip_from 2c0f:f248::/32; + +real_ip_header CF-Connecting-IP; diff --git a/roles/frontend/templates/dmca b/roles/frontend/templates/dmca new file mode 100644 index 0000000..e7fbe6e --- /dev/null +++ b/roles/frontend/templates/dmca @@ -0,0 +1,4 @@ +# Example +#location = /cache/media_attachments/files/109/437/372/880/064/218/original/3260dbbf5bbdce0e.jpg { +# deny all; +#} diff --git a/roles/frontend/templates/files.j2 b/roles/frontend/templates/files.j2 new file mode 100644 index 0000000..023a52d --- /dev/null +++ b/roles/frontend/templates/files.j2 @@ -0,0 +1,90 @@ +server { + listen 80; + listen [::]:80; + server_name {{ ENV_PRODUCTION['S3_ALIAS_HOST'] }}; + root /var/www/html; + # Useful for Let's Encrypt + location /.well-known/acme-challenge/ { allow all; } + location / { return 301 https://$host$request_uri; } +} + +log_format files_cache '$remote_addr - $upstream_cache_status [$time_local] ' + '"$request" $status $body_bytes_sent ' + '"$http_referer" "$http_user_agent"'; + +proxy_cache_path /data/nginx/cache keys_zone=mycache:50m inactive=3d; + +server { + listen 443 ssl http2; + listen [::]:443 ssl http2; + server_name {{ ENV_PRODUCTION['S3_ALIAS_HOST'] }}; + root /var/www/html; + + include /etc/nginx/cloudflare; + + ssl_certificate /etc/letsencrypt/live/{{ ENV_PRODUCTION['S3_ALIAS_HOST'] }}/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/{{ ENV_PRODUCTION['S3_ALIAS_HOST'] }}/privkey.pem; + + access_log /var/log/nginx/{{ ENV_PRODUCTION['S3_ALIAS_HOST'] }}.access.log files_cache; + error_log /var/log/nginx/{{ ENV_PRODUCTION['S3_ALIAS_HOST'] }}.error.log; + + proxy_cache mycache; + keepalive_timeout 30; + + # Don't allow directory listings + location ~ ^.*/$ { + deny all; + } + + include /etc/nginx/dmca; + + location ~ .+ { + try_files $uri @s3; + } + + set $s3_backend '{{ ENV_PRODUCTION['S3_HOSTNAME'] }}'; + + location @s3 { + limit_except GET { + deny all; + } + + resolver 8.8.8.8; + proxy_set_header Host yttrx.sfo3.digitaloceanspaces.com; + proxy_set_header Connection ''; + proxy_set_header Authorization ''; + proxy_hide_header Set-Cookie; + proxy_hide_header 'Access-Control-Allow-Origin'; + proxy_hide_header 'Access-Control-Allow-Methods'; + proxy_hide_header 'Access-Control-Allow-Headers'; + #proxy_hide_header x-amz-id-2; + #proxy_hide_header x-amz-request-id; + #proxy_hide_header x-amz-meta-server-side-encryption; + #proxy_hide_header x-amz-server-side-encryption; + #proxy_hide_header x-amz-bucket-region; + #proxy_hide_header x-amzn-requestid; + proxy_ignore_headers Set-Cookie; + proxy_pass $s3_backend$uri; + #proxy_intercept_errors off; + # turn this on so that we can capture and redirect bad links to the main 404 page + proxy_intercept_errors on; + + #proxy_cache_valid 200 48h; + proxy_cache_valid 48h; + proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504; + proxy_cache_lock on; + proxy_cache_key $uri; + + # Download stale data only if it has been modified on origin + proxy_cache_revalidate off; + + expires 30d; + add_header Pragma public; + add_header Cache-Control "public"; + add_header 'Access-Control-Allow-Origin' '*'; + add_header X-Cache-Status $upstream_cache_status; + + error_page 403 https://{{ ENV_PRODUCTION['LOCAL_DOMAIN'] }}/404.html; + error_page 404 https://{{ ENV_PRODUCTION['LOCAL_DOMAIN'] }}/404.html; + } +} diff --git a/roles/frontend/templates/mastodon.j2 b/roles/frontend/templates/mastodon.j2 new file mode 100644 index 0000000..a1dfc8e --- /dev/null +++ b/roles/frontend/templates/mastodon.j2 @@ -0,0 +1,117 @@ +map $http_upgrade $connection_upgrade { + default upgrade; + '' close; +} + +server { + listen 80; + listen [::]:80; + server_name {{ ENV_PRODUCTION['LOCAL_DOMAIN'] }} + root /home/mastodon/live/public; + # Useful for Let's Encrypt + location /.well-known/acme-challenge/ { allow all; } + location / { return 301 https://$host$request_uri; } +} + +upstream webbackend { +{% for server in webapp_hosts %} + server {{ server }}:3000; +{% endfor %} +} + +upstream streamingbackend { +{% for server in webapp_hosts %} + server {{ server }}:4000; +{% endfor %} +} + +server { + listen 443 ssl http2; + listen [::]:443 ssl http2; + server_name {{ ENV_PRODUCTION['LOCAL_DOMAIN'] }}; + + include /etc/nginx/cloudflare; + + ssl_protocols TLSv1.2; + ssl_ciphers HIGH:!MEDIUM:!LOW:!aNULL:!NULL:!SHA; ssl_prefer_server_ciphers on; + ssl_session_cache shared:SSL:10m; + + ssl_certificate /etc/letsencrypt/live/{{ ENV_PRODUCTION['LOCAL_DOMAIN'] }}/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/{{ ENV_PRODUCTION['LOCAL_DOMAIN'] }}/privkey.pem; + + keepalive_timeout 70; + sendfile on; + client_max_body_size 80m; + + root /home/mastodon/live/public; + + gzip on; + gzip_disable "msie6"; + gzip_vary on; + gzip_proxied any; + gzip_comp_level 6; + gzip_buffers 16 8k; + gzip_http_version 1.1; + gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; + + add_header Strict-Transport-Security "max-age=31536000"; + + location / { + try_files $uri @proxy; + } + + # WITH S3 + location ~ ^/(emoji|packs) { + add_header Cache-Control "public, max-age=31536000, immutable"; + try_files $uri @proxy; + } + + location /system { + rewrite ^/system(.*) https://{{ ENV_PRODUCTION['S3_ALIAS_HOST'] }}$1 permanent; + } + # END OF S3 + location /sw.js { + #add_header Cache-Control "public, max-age=0"; + add_header Cache-Control "public, max-age=604800, must-revalidate"; + add_header Strict-Transport-Security "max-age=63072000; includeSubDomains"; + try_files $uri @proxy; + } + + location @proxy { + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto https; + proxy_set_header Proxy ""; + proxy_pass_header Server; + + + proxy_pass http://webbackend; + proxy_buffering off; + proxy_redirect off; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + + tcp_nodelay on; + } + + location /api/v1/streaming { + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto https; + proxy_set_header Proxy ""; + + proxy_pass http://streamingbackend; + proxy_buffering off; + proxy_redirect off; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + + tcp_nodelay on; + } + + error_page 500 501 502 503 504 /500.html; +} diff --git a/roles/frontend/templates/status b/roles/frontend/templates/status new file mode 100644 index 0000000..0730f85 --- /dev/null +++ b/roles/frontend/templates/status @@ -0,0 +1,19 @@ +server { + listen 81 default_server; + listen [::]:81 default_server; + + root /var/www/html; + index index.html index.htm index.nginx-debian.html; + + server_name _; + + location / { + try_files $uri $uri/ =404; + } + + location /nginx_status { + stub_status; + #allow 127.0.0.1; + #deny all; + } +} diff --git a/roles/frontend/templates/tusky b/roles/frontend/templates/tusky new file mode 100644 index 0000000..40abe0b --- /dev/null +++ b/roles/frontend/templates/tusky @@ -0,0 +1,76 @@ +## +# You should look at the following URL's in order to grasp a solid understanding +# of Nginx configuration files in order to fully unleash the power of Nginx. +# https://www.nginx.com/resources/wiki/start/ +# https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/ +# https://wiki.debian.org/Nginx/DirectoryStructure +# +# In most cases, administrators will remove this file from sites-enabled/ and +# leave it as reference inside of sites-available where it will continue to be +# updated by the nginx packaging team. +# +# This file will automatically load configuration files provided by other +# applications, such as Drupal or Wordpress. These applications will be made +# available underneath a path with that package name, such as /drupal8. +# +# Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples. +## + +# Default server configuration +# + +server { + listen 80; + listen [::]:80; + server_name tusky.yttrx.com; + root /var/www/html/tusky; + # Useful for Let's Encrypt + location /.well-known/acme-challenge/ { allow all; } + location / { return 301 https://$host$request_uri; } +} + +server { + listen 443 ssl http2; + listen [::]:443 ssl http2; + server_name tusky.yttrx.com; + root /var/www/html/tusky; + + ssl_certificate /etc/letsencrypt/live/tusky.yttrx.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/tusky.yttrx.com/privkey.pem; + access_log /var/log/nginx/tusky.access.log; + error_log /var/log/nginx/static.error.log; + + + location / { + # First attempt to serve request as file, then + # as directory, then fall back to displaying a 404. + try_files $uri $uri/ =404; + } + + location /statsd { + try_files $uri @proxy; + } + + location /metrics { + try_files $uri @proxy; + } + + location @proxy { + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto https; + proxy_set_header Proxy ""; + + proxy_pass http://127.0.0.1:9102; + proxy_buffering off; + proxy_redirect off; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + + tcp_nodelay on; + } + +} + diff --git a/roles/frontend/templates/waffles b/roles/frontend/templates/waffles new file mode 100644 index 0000000..011355e --- /dev/null +++ b/roles/frontend/templates/waffles @@ -0,0 +1,57 @@ +## +# You should look at the following URL's in order to grasp a solid understanding +# of Nginx configuration files in order to fully unleash the power of Nginx. +# https://www.nginx.com/resources/wiki/start/ +# https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/ +# https://wiki.debian.org/Nginx/DirectoryStructure +# +# In most cases, administrators will remove this file from sites-enabled/ and +# leave it as reference inside of sites-available where it will continue to be +# updated by the nginx packaging team. +# +# This file will automatically load configuration files provided by other +# applications, such as Drupal or Wordpress. These applications will be made +# available underneath a path with that package name, such as /drupal8. +# +# Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples. +## + +# Default server configuration +# + +server { + listen 80; + listen [::]:80; + server_name waffles.yttrx.com; + root /var/www/html/waffles; + # Useful for Let's Encrypt + location /.well-known/acme-challenge/ { allow all; } + location / { return 301 https://$host$request_uri; } +} + +server { + listen 443 ssl http2; + listen [::]:443 ssl http2; + server_name waffles.yttrx.com; + root /var/www/html/waffles; + + include /etc/nginx/cloudflare; + ssl_certificate /etc/letsencrypt/live/waffles.yttrx.com/fullchain.pem; # managed by Certbot + ssl_certificate_key /etc/letsencrypt/live/waffles.yttrx.com/privkey.pem; # managed by Certbot + access_log /var/log/nginx/waffles.access.log; + error_log /var/log/nginx/waffles.error.log; + + location = /.well-known/webfinger { + types {} default_type "application/jrd+json"; + add_header Access-Control-Allow-Origin "*"; + } + + location / { + # First attempt to serve request as file, then + # as directory, then fall back to displaying a 404. + try_files $uri $uri/ =404; + } + + +} + diff --git a/roles/frontend/vars/main.yml b/roles/frontend/vars/main.yml new file mode 100644 index 0000000..ed97d53 --- /dev/null +++ b/roles/frontend/vars/main.yml @@ -0,0 +1 @@ +--- diff --git a/roles/mastodon/meta/main.yml b/roles/mastodon/meta/main.yml new file mode 100644 index 0000000..c0ff46d --- /dev/null +++ b/roles/mastodon/meta/main.yml @@ -0,0 +1,4 @@ +--- +dependencies: + - role: geerlingguy.docker + - role: yttrx diff --git a/roles/mastodon/tasks/main.yml b/roles/mastodon/tasks/main.yml new file mode 100644 index 0000000..28679ac --- /dev/null +++ b/roles/mastodon/tasks/main.yml @@ -0,0 +1,32 @@ +--- +# Setup users etc +- name: create the mastodon user account + user: + name: mastodon + shell: /bin/bash + group: docker + +- name: Check if mastodon repo checked out + stat: path=/home/mastodon/live + register: p + +- import_tasks: swap.yml + +- import_tasks: repo.yml + when: not p.stat.exists + +- name: Install statsd mapper + template: + src: statsd-mapping.yaml.j2 + dest: /root/statsd-mapping.yml + +- name: Install .env.production file + template: + src: env.production.j2 + dest: /home/mastodon/live/.env.production + +- name: Install docker-compose.yml file + template: + src: docker-compose.yml.j2 + dest: /home/mastodon/live/docker-compose.yml + notify: "docker-compose up" diff --git a/roles/mastodon/tasks/repo.yml b/roles/mastodon/tasks/repo.yml new file mode 100644 index 0000000..4fff7e4 --- /dev/null +++ b/roles/mastodon/tasks/repo.yml @@ -0,0 +1,7 @@ +--- +- name: clone mastodon repo + git: + repo: https://github.com/mastodon/mastodon.git + dest: /home/mastodon/live + version: v4.0.2 + diff --git a/roles/mastodon/tasks/swap.yml b/roles/mastodon/tasks/swap.yml new file mode 100644 index 0000000..3441daa --- /dev/null +++ b/roles/mastodon/tasks/swap.yml @@ -0,0 +1,36 @@ +- name: set swap_file variable + set_fact: + swap_file: /{{ swap_space }}.swap + +- name: check if swap file exists + stat: + path: "{{ swap_file }}" + register: swap_file_check + +- name: create swap file + command: fallocate -l {{ swap_space }} {{ swap_file }} + args: + creates: /{{ swap_file }} + +- name: set permissions on swap file + file: + path: "{{ swap_file }}" + mode: 0600 + +- name: format swap file + command: mkswap {{ swap_file }} + when: not swap_file_check.stat.exists + +- name: add to fstab + lineinfile: + dest: /etc/fstab + regexp: "{{ swap_file }}" + line: "{{ swap_file }} none swap sw 0 0" + +- name: turn on swap + command: swapon -a + +- name: set swapiness + sysctl: + name: vm.swappiness + value: "1" diff --git a/roles/mastodon/templates/docker-compose.sidekiq-default.yml.j2 b/roles/mastodon/templates/docker-compose.sidekiq-default.yml.j2 new file mode 100644 index 0000000..4e9638b --- /dev/null +++ b/roles/mastodon/templates/docker-compose.sidekiq-default.yml.j2 @@ -0,0 +1,20 @@ + + sidekiq-default: + image: tootsuite/mastodon:{{ MASTODON_VERSION }} + restart: always + env_file: .env.production + command: bundle exec sidekiq -q default -c 5 + depends_on: + - pgbouncer + networks: + - external_network + - internal_network + volumes: + - ./public/system:/mastodon/public/system + - ./config:/opt/mastodon/config + environment: +{% if DB_POOL is defined %} + - 'DB_POOL={{ DB_POOL }}' +{% endif %} + healthcheck: + test: ['CMD-SHELL', "ps aux | grep '[s]idekiq\ 6' || false"] diff --git a/roles/mastodon/templates/docker-compose.sidekiq-ingress.yml.j2 b/roles/mastodon/templates/docker-compose.sidekiq-ingress.yml.j2 new file mode 100644 index 0000000..6c8d0da --- /dev/null +++ b/roles/mastodon/templates/docker-compose.sidekiq-ingress.yml.j2 @@ -0,0 +1,19 @@ + # sidekiq-ingress + sidekiq-ingress: + image: tootsuite/mastodon:{{ MASTODON_VERSION }} + restart: always + env_file: .env.production + command: bundle exec sidekiq -q ingress + depends_on: + - pgbouncer + networks: + - external_network + - internal_network + volumes: + - ./public/system:/mastodon/public/system + - ./config:/opt/mastodon/config + environment: + - 'DB_POOL=25' + healthcheck: + test: ['CMD-SHELL', "ps aux | grep '[s]idekiq\ 6' || false"] + diff --git a/roles/mastodon/templates/docker-compose.sidekiq-mailers.yml.j2 b/roles/mastodon/templates/docker-compose.sidekiq-mailers.yml.j2 new file mode 100644 index 0000000..b558eea --- /dev/null +++ b/roles/mastodon/templates/docker-compose.sidekiq-mailers.yml.j2 @@ -0,0 +1,20 @@ + + sidekiq-mailers: + image: tootsuite/mastodon:{{ MASTODON_VERSION }} + restart: always + env_file: .env.production + command: bundle exec sidekiq -q mailers -c 5 + depends_on: + - pgbouncer + networks: + - external_network + - internal_network + volumes: + - ./public/system:/mastodon/public/system + - ./config:/opt/mastodon/config + environment: + - 'DB_POOL=25' + healthcheck: + test: ['CMD-SHELL', "ps aux | grep '[s]idekiq\ 6' || false"] + + diff --git a/roles/mastodon/templates/docker-compose.sidekiq-pushpull.yml.j2 b/roles/mastodon/templates/docker-compose.sidekiq-pushpull.yml.j2 new file mode 100644 index 0000000..03661ab --- /dev/null +++ b/roles/mastodon/templates/docker-compose.sidekiq-pushpull.yml.j2 @@ -0,0 +1,19 @@ + + sidekiq-pushpull: + image: tootsuite/mastodon:{{ MASTODON_VERSION }} + restart: always + env_file: .env.production + command: bundle exec sidekiq -q push -q pull -c 5 + depends_on: + - pgbouncer + networks: + - external_network + - internal_network + volumes: + - ./public/system:/mastodon/public/system + - ./config:/opt/mastodon/config + environment: + - 'DB_POOL=25' + healthcheck: + test: ['CMD-SHELL', "ps aux | grep '[s]idekiq\ 6' || false"] + diff --git a/roles/mastodon/templates/docker-compose.sidekiq-scheduler.yml.j2 b/roles/mastodon/templates/docker-compose.sidekiq-scheduler.yml.j2 new file mode 100644 index 0000000..f21faa1 --- /dev/null +++ b/roles/mastodon/templates/docker-compose.sidekiq-scheduler.yml.j2 @@ -0,0 +1,19 @@ + + sidekiq-scheduler: + image: tootsuite/mastodon:{{ MASTODON_VERSION }} + restart: always + env_file: .env.production + command: bundle exec sidekiq -q scheduler + depends_on: + - pgbouncer + networks: + - external_network + - internal_network + volumes: + - ./public/system:/mastodon/public/system + - ./config:/opt/mastodon/config + environment: + - 'DB_POOL=25' + healthcheck: + test: ['CMD-SHELL', "ps aux | grep '[s]idekiq\ 6' || false"] + diff --git a/roles/mastodon/templates/docker-compose.sidekiq.yml.j2 b/roles/mastodon/templates/docker-compose.sidekiq.yml.j2 new file mode 100644 index 0000000..b658a9b --- /dev/null +++ b/roles/mastodon/templates/docker-compose.sidekiq.yml.j2 @@ -0,0 +1,15 @@ + sidekiq: + image: tootsuite/mastodon:{{ MASTODON_VERSION }} + restart: always + env_file: .env.production + command: bundle exec sidekiq + depends_on: + - pgbouncer + networks: + - external_network + - internal_network + volumes: + - ./public/system:/mastodon/public/system + - ./config:/opt/mastodon/config + healthcheck: + test: ['CMD-SHELL', "ps aux | grep '[s]idekiq\ 6' || false"] diff --git a/roles/mastodon/templates/docker-compose.yml.j2 b/roles/mastodon/templates/docker-compose.yml.j2 new file mode 100644 index 0000000..c54bd44 --- /dev/null +++ b/roles/mastodon/templates/docker-compose.yml.j2 @@ -0,0 +1,33 @@ +version: '3' +services: +{% if ENV_PRODUCTION['STATSD_ADDR'] is defined %} + statsd: + restart: always + image: prom/statsd-exporter + command: --statsd.mapping-config=/tmp/statsd_mapping.yml + volumes: + - /root/statsd-mapping.yml:/tmp/statsd_mapping.yml + networks: + - internal_network + - external_network + ports: + - 9102:9102 + - "127.0.0.1:9125:9125" +{% endif %} + pgbouncer: + restart: always + image: edoburu/pgbouncer + networks: + - internal_network + - external_network + environment: + - 'DB_HOST={{ REAL_DB_HOST }}' + - 'DB_NAME={{ ENV_PRODUCTION["DB_NAME"] }}' + - 'DB_USER={{ ENV_PRODUCTION["DB_USER"] }}' + - 'DB_PASSWORD={{ ENV_PRODUCTION["DB_PASS"] }}' + - 'SERVER_TLS_SSLMODE=prefer' + +networks: + external_network: + internal_network: + internal: true diff --git a/roles/mastodon/templates/env.production.j2 b/roles/mastodon/templates/env.production.j2 new file mode 100644 index 0000000..1934902 --- /dev/null +++ b/roles/mastodon/templates/env.production.j2 @@ -0,0 +1,3 @@ +{% for key, val in ENV_PRODUCTION.items() %} +{{ key }}={{ val }} +{% endfor %} diff --git a/roles/mastodon/templates/statsd-mapping.yaml.j2 b/roles/mastodon/templates/statsd-mapping.yaml.j2 new file mode 100644 index 0000000..2f79cab --- /dev/null +++ b/roles/mastodon/templates/statsd-mapping.yaml.j2 @@ -0,0 +1,96 @@ +## Prometheus Statsd Exporter mapping for Mastodon 4.0+ +## +## Version 1.0, November 2022 +## +## Documentation: https://ipng.ch/s/articles/2022/11/27/mastodon-3.html + +mappings: + ## Web collector + - match: Mastodon\.production\.web\.(.+)\.(.+)\.(.+)\.status\.(.+) + match_type: regex + name: "mastodon_controller_status" + labels: + controller: $1 + action: $2 + format: $3 + status: $4 + mastodon: "web" + - match: Mastodon\.production\.web\.(.+)\.(.+)\.(.+)\.db_time + match_type: regex + name: "mastodon_controller_db_time" + labels: + controller: $1 + action: $2 + format: $3 + mastodon: "web" + - match: Mastodon\.production\.web\.(.+)\.(.+)\.(.+)\.view_time + match_type: regex + name: "mastodon_controller_view_time" + labels: + controller: $1 + action: $2 + format: $3 + mastodon: "web" + - match: Mastodon\.production\.web\.(.+)\.(.+)\.(.+)\.total_duration + match_type: regex + name: "mastodon_controller_duration" + labels: + controller: $1 + action: $2 + format: $3 + mastodon: "web" + + ## Database collector + - match: Mastodon\.production\.db\.tables\.(.+)\.queries\.(.+)\.duration + match_type: regex + name: "mastodon_db_operation" + labels: + table: "$1" + operation: "$2" + mastodon: "db" + + ## Cache collector + - match: Mastodon\.production\.cache\.(.+)\.duration + match_type: regex + name: "mastodon_cache_duration" + labels: + operation: "$1" + mastodon: "cache" + + ## Sidekiq collector + - match: Mastodon\.production\.sidekiq\.(.+)\.processing_time + match_type: regex + name: "mastodon_sidekiq_worker_processing_time" + labels: + worker: "$1" + mastodon: "sidekiq" + - match: Mastodon\.production\.sidekiq\.(.+)\.success + match_type: regex + name: "mastodon_sidekiq_worker_success_total" + labels: + worker: "$1" + mastodon: "sidekiq" + - match: Mastodon\.production\.sidekiq\.(.+)\.failure + match_type: regex + name: "mastodon_sidekiq_worker_failure_total" + labels: + worker: "$1" + mastodon: "sidekiq" + - match: Mastodon\.production\.sidekiq\.queues\.(.+)\.enqueued + match_type: regex + name: "mastodon_sidekiq_queue_enqueued" + labels: + queue: "$1" + mastodon: "sidekiq" + - match: Mastodon\.production\.sidekiq\.queues\.(.+)\.latency + match_type: regex + name: "mastodon_sidekiq_queue_latency" + labels: + queue: "$1" + mastodon: "sidekiq" + - match: Mastodon\.production\.sidekiq\.(.+) + match_type: regex + name: "mastodon_sidekiq_$1" + labels: + mastodon: "sidekiq" + diff --git a/roles/sidekiq/meta/main.yml b/roles/sidekiq/meta/main.yml new file mode 100644 index 0000000..6786fd2 --- /dev/null +++ b/roles/sidekiq/meta/main.yml @@ -0,0 +1,3 @@ +--- +dependencies: + - role: mastodon diff --git a/roles/sidekiq/tasks/main.yml b/roles/sidekiq/tasks/main.yml new file mode 100644 index 0000000..af9403d --- /dev/null +++ b/roles/sidekiq/tasks/main.yml @@ -0,0 +1,6 @@ +--- + - name: Configure docker-compose.override.yml + template: + src: docker-compose.override.yml.j2 + dest: /home/mastodon/live/docker-compose.override.yml + notify: "docker-compose up" diff --git a/roles/sidekiq/templates/docker-compose.override.yml.j2 b/roles/sidekiq/templates/docker-compose.override.yml.j2 new file mode 100644 index 0000000..b014b62 --- /dev/null +++ b/roles/sidekiq/templates/docker-compose.override.yml.j2 @@ -0,0 +1,23 @@ +services: +{% for SK in sidekiq %} + sidekiq-{{ SK['name'] }}: + image: tootsuite/mastodon:{{ MASTODON_VERSION }} + restart: always + env_file: .env.production +{% if 'q' in SK %} + command: bundle exec sidekiq {{ SK['q'] | join(' ') }} -c 10 +{% else %} + command: bundle exec sidekiq +{% endif %} + depends_on: + - pgbouncer + networks: + - external_network + - internal_network + volumes: + - ./public/system:/mastodon/public/system + - ./config:/opt/mastodon/config + healthcheck: + test: ['CMD-SHELL', "ps aux | grep '[s]idekiq\ 6' || false"] + +{% endfor %} diff --git a/roles/webapp/meta/main.yml b/roles/webapp/meta/main.yml new file mode 100644 index 0000000..2057a43 --- /dev/null +++ b/roles/webapp/meta/main.yml @@ -0,0 +1,4 @@ +--- +dependencies: + - role: geerlingguy.nginx + - role: mastodon diff --git a/roles/webapp/tasks/main.yml b/roles/webapp/tasks/main.yml new file mode 100644 index 0000000..3df08a7 --- /dev/null +++ b/roles/webapp/tasks/main.yml @@ -0,0 +1,6 @@ +--- + - name: Configure docker-compose.yml + template: + src: docker-compose.override.yml.j2 + dest: /home/mastodon/live/docker-compose.override.yml + notify: "docker-compose up" diff --git a/roles/webapp/templates/docker-compose.override.yml.j2 b/roles/webapp/templates/docker-compose.override.yml.j2 new file mode 100644 index 0000000..1c26e00 --- /dev/null +++ b/roles/webapp/templates/docker-compose.override.yml.j2 @@ -0,0 +1,38 @@ +version: '3' +services: + web: + image: tootsuite/mastodon:v4.0.2 + restart: always + env_file: .env.production + command: bash -c "rm -f /mastodon/tmp/pids/server.pid; bundle exec rails s -p 3000" + networks: + - external_network + - internal_network + healthcheck: + test: ['CMD-SHELL', 'wget -q --spider --proxy=off localhost:3000/health || exit 1'] + ports: + - 3000:3000 + depends_on: + - pgbouncer + environment: + - 'MAX_THREADS=10' + - 'WEB_CONCURRENCY=3' + volumes: + - ./public/system:/mastodon/public/system + + streaming: + image: tootsuite/mastodon:v4.0.2 + restart: always + env_file: .env.production + command: node ./streaming + networks: + - external_network + - internal_network + healthcheck: + test: ['CMD-SHELL', 'wget -q --spider --proxy=off localhost:4000/api/v1/streaming/health || exit 1'] + environment: + - 'DB_POOL=25' + ports: + - 4000:4000 + depends_on: + - pgbouncer diff --git a/roles/yttrx/meta/main.yml b/roles/yttrx/meta/main.yml new file mode 100644 index 0000000..c9e71f5 --- /dev/null +++ b/roles/yttrx/meta/main.yml @@ -0,0 +1,12 @@ +--- +dependencies: + - role: ansible-role-neovim + - role: geerlingguy.docker + - role: ansible-role-oh-my-zsh + vars: + users: + - username: root + oh_my_zsh: + theme: agnoster + plugins: + - git diff --git a/roles/yttrx/tasks/main.yml b/roles/yttrx/tasks/main.yml new file mode 100644 index 0000000..385049b --- /dev/null +++ b/roles/yttrx/tasks/main.yml @@ -0,0 +1,27 @@ +--- +- name: Install prometheus node exporter + package: + name: prometheus-node-exporter + state: present + +- name: Create nvim config dir + file: + path: /root/.config/nvim + state: directory + +- name: Install nvim config file + template: + src: templates/nvim/init.vim.j2 + dest: /root/.config/nvim/init.vim + +- name: Install nvim plugins + command: nvim --headless +PluginInstall +qall + args: + creates: /root/.vim/bundle/ + +- name: Clone fzf + git: + repo: https://github.com/junegunn/fzf + dest: /root/fzf + clone: yes + update: yes diff --git a/sidekiq.yml b/sidekiq.yml new file mode 100644 index 0000000..adb969c --- /dev/null +++ b/sidekiq.yml @@ -0,0 +1,20 @@ +--- +- name: Configure yttrx sidekiq environment + hosts: [sidekiq] + roles: + - role: sidekiq + vars: + sidekiq: + - name: ingress + q: [ '-q', 'ingress', '-q', 'push', ] + - name: + q: [ '-q', 'pull', '-q', 'default' ] + + handlers: + - name: Re-up docker containers + command: docker-compose up -d --remove-orphans + args: + chdir: /home/mastodon/live + listen: "docker-compose up" + + diff --git a/templates/nvim/init.vim.j2 b/templates/nvim/init.vim.j2 new file mode 100644 index 0000000..16a5567 --- /dev/null +++ b/templates/nvim/init.vim.j2 @@ -0,0 +1,408 @@ +" Setup runtime path +let s:editor_root=expand("~/.vim") +let &rtp = &rtp . ',' . s:editor_root . '/bundle/Vundle.vim' + +" Install Vundle if not present +let vundle_installed=1 +let vundle_readme=s:editor_root . '/bundle/Vundle.vim/README.md' +let vundle_repo = 'https://github.com/VundleVim/Vundle.vim' + +if !filereadable(vundle_readme) + echo "Installing Vundle.." + echo "" + silent call mkdir(s:editor_root . '/bundle', "p") + silent execute "!git clone " . vundle_repo . " " . s:editor_root . "/bundle/Vundle.vim" + let vundle_installed=0 +endif + +call vundle#rc(s:editor_root . '/bundle') +call vundle#begin() + +Plugin 'VundleVim/Vundle.vim' +Plugin 'airblade/vim-gitgutter' +Plugin 'vim-airline/vim-airline-themes' +Plugin 'jeffkreeftmeijer/vim-numbertoggle' +Plugin 'majutsushi/tagbar' +Plugin 'blueyed/vim-diminactive' +Plugin 'tell-k/vim-autopep8' +Plugin 'mhinz/vim-signify' + + +" Syntax plugins +"Plugin 'tmhedberg/SimpylFold' +Plugin 'trapd00r/irc.vim' +Plugin 'PotatoesMaster/i3-vim-syntax' +Plugin 'ClockworkNet/vim-junos-syntax' +Plugin 'nathanalderson/yang.vim' +Plugin 'mitsuhiko/vim-jinja' +Plugin 'sheerun/vim-polyglot' +Plugin 'ekalinin/Dockerfile.vim' +"Plugin 'fatih/vim-go' +Plugin 'rust-lang/rust.vim' +Plugin 'hhvm/vim-hack' + +" Color schemes +Plugin 'chriskempson/base16-vim' +Plugin 'tomasr/molokai' +Plugin 'joshdick/onedark.vim' +Plugin 'arakashic/nvim-colors-solarized' +Plugin 'drewtempelmeyer/palenight.vim' +Plugin 'skbolton/embark' + +Plugin 'guns/xterm-color-table.vim' + +" Airline +" Plugin 'joshdick/airline-onedark.vim' +Plugin 'vim-airline/vim-airline' +Plugin 'bling/vim-bufferline' + +" Utility plugins +Plugin 'benmills/vimux' +"Plugin 'neomake/neomake' +" Plugin 'coxley/codepad' +Plugin 'keith/gist.vim' +Plugin 'nvie/vim-flake8' +" Plugin 'ntpeters/vim-better-whitespace' +Plugin 'suan/vim-instant-markdown' +Plugin 'dhruvasagar/vim-table-mode' +Plugin 'powerline/powerline' +" Plugin 'kana/vim-fakeclip' +Plugin 'petermblair/vim-arcanist' +Plugin 'phleet/vim-mercenary' +Plugin 'hynek/vim-python-pep8-indent' +Plugin 'tpope/vim-abolish' +Plugin 'junegunn/fzf.vim' +Plugin 'christoomey/vim-tmux-navigator' +Plugin 'flazz/vim-colorschemes' +Plugin 'jbgutierrez/vim-better-comments' +" Ranger integration +"Plugin 'francoiscabrol/ranger.vim' +"Plugin 'w0rp/ale' +" Powerhouse plugins +Plugin 'Rykka/riv.vim' +" Plugin 'Rykka/InstantRst' +" Plugin 'sjl/gundo.vim' +" Plugin 'tomtom/tcomment_vim' +Plugin 'scrooloose/nerdtree' +Plugin 'godlygeek/tabular' +Plugin 'Shougo/deoplete.nvim' +Plugin 'zchee/deoplete-clang' +" Vim go completion +Plugin 'nsf/gocode', {'rtp': 'vim/'} +"Plugin 'davidhalter/jedi-vim' +"Plugin 'deoplete-plugins/deoplete-jedi' +" Plugin 'SirVer/ultisnips' +" Plugin 'honza/vim-snippets' +Plugin 'ervandew/supertab' +" Plugin 'Yggdroot/indentLine' +" Plugin 'terryma/vim-expand-region' + +" Distraction free +" Plugin 'junegunn/goyo.vim' +" Plugin 'junegunn/limelight.vim' + +" C++ +Plugin 'vim-scripts/a.vim' + +" Web Development +" Plugin 'mattn/emmet-vim' +Plugin 'chrisbra/Colorizer' +Plugin 'jelera/vim-javascript-syntax' + +call vundle#end() + +let g:python3_host_prog = '/usr/bin/python3' + +"let g:onedark_termcolors=256 + +let g:deoplete#enable_at_startup = 1 +"let g:deoplete#sources = ['buffer', 'tag'] + +let g:deoplete#sources#clang#libclang_path = '/usr/lib/libclang.so' +let g:deoplete#sources#clang#clang_header = '/usr/lib/clang' + +autocmd FileType python nnoremap y :0,$!yapf +autocmd CompleteDone * pclose " To close preview window of deoplete + +syntax enable +set background=dark +set termguicolors + +if !exists('g:colors_name') || g:colors_name != 'base16-flat' + colorscheme base16-flat +endif + +" Italics for my favorite color scheme +let g:palenight_terminal_italics=1 + +" " be kind to the 80 character limit +" " Create a giant wall of highlight past 80 characters +"let &colorcolumn=join(range(81,999),",") +highlight colorcolumn ctermbg=235 guibg=#2c2d27 + +" Toggle search hilighting with f3 +nnoremap :set hlsearch! +" Don't hilight searches +set nohlsearch + +" Remap the leader key +" let mapleader = "\" +"let mapleader = "\\" + +" remap ; to : so that ;w works instead of :w +nnoremap ; : + +" remap key as jj +"inoremap jj +" Same for jj +inoremap jk +inoremap kj + +" quickly clear highlights +map n :noh + +" quickly close quickfix +map C :ccl + +" quickly open a new tab +map T :tabnew + +" no more pesky escape (for insert and visual mode) +imap kj +imap kJ +imap Kj +imap KJ + +" vv to generate a new vertical split +nnoremap vv v + +" Navigate buffers +" Tab navigation like Firefox. +nnoremap :bnext + +" Find all occurances under cursor within file +nnoremap ff g# + +" map leader rv to resize window to 80 columns +nnoremap rr :vertical resize 86 + +" Manage tabs with jk +nnoremap j :tabp +nnoremap k :tabn + +" Buffer navigation like Firefox. +nnoremap :bprev +nnoremap :bnext + +" manage the buffers +nnoremap [ :bprev +nnoremap ] :bnext:w + +"set list +set hidden +set ai +set magic +set mouse=a +set number +set ignorecase +set smartcase +set hlsearch +set incsearch +set pastetoggle= +set cursorline " hilight the current line +set splitright +"set splitbelow +set tags=~/mytags + +:au FocusLost * :set number +:au FocusGained * :set relativenumber + +" Make splits nicer +nnoremap +nnoremap +nnoremap +nnoremap + +" Show just the filename +let g:airline#extensions#tabline#fnamemod = ':t' + +" used patched fonts for airline arrows/triangles +let g:airline_powerline_fonts=1 + +let g:airline#extensions#tabline#enabled = 1 +let g:airline#extensions#tabline#show_buffers = 0 +let g:airline#extensions#tabline#show_close_button = 0 + +" Ensure that for Makefiles we don't replace TABs with spaces +let _curfile = expand("%:t") +if _curfile =~ "Makefile" || _curfile =~ "makefile" || _curfile =~ ".*\mk" + set noexpandtab +else + " Don't use tabs, use spaces + set expandtab + + " make tab insert indents instead of tabs at begining of line + set smarttab +endif + +" Tell vim to treat certain files with python syntax +au BufRead,BufNewFile *.cconf set filetype=python +au BufRead,BufNewFile *.cinc set filetype=python +au BufRead,BufNewFile *.thrift set filetype=thrift +au BufRead,BufNewFile TARGETS set filetype=python +au! Syntax thrift source $LOCAL_ADMIN_SCRIPTS/vim/syntax/thrift.vim + +" NERDTree - map Ctrl+n to toggle the tree on/off +nnoremap :NERDTreeToggle +nnoremap :autopep8 +nnoremap :TagbarToggle + +" Configures ripgrep with fzf +command! -bang -nargs=* FzfRg call fzf#vim#grep("rg --column --line-number --no-heading --color=always --smart-case ".shellescape(), 1, {'options': '--delimiter : --nth 4..'}, 0) +command! -bang -nargs=* Rgg call fzf#vim#grep("rg --no-ignore --column --line-number --no-heading --color=always --smart-case ".shellescape(), 1, {'options': '--delimiter : --nth 4..'}, 0) + +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" https://github.com/christoomey/vim-tmux-navigator +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +source ~/.vim/bundle/vim-tmux-navigator/plugin/tmux_navigator.vim + + +let g:tmux_navigator_no_mappings = 1 + +nnoremap {Left-mapping} :TmuxNavigateLeft +nnoremap {Down-Mapping} :TmuxNavigateDown +nnoremap {Up-Mapping} :TmuxNavigateUp +nnoremap {Right-Mapping} :TmuxNavigateRight +nnoremap {Previous-Mapping} :TmuxNavigatePrevious + +"############################################################################# +" Mappings +"############################################################################# + +" Next buffer +nnoremap :bnext +" Previous buffer +nnoremap :bprevious +" Create vsplit +nnoremap \| :vsp +" Creat hsplit +nnoremap - :sp +" Save file +nnoremap w :w +" Open startify with leader l +nnoremap l :Startify +" Open fuzzy files with leader \ +nnoremap \ :Files +" Open fuzzy lines with leader o +nnoremap o :Lines +" Open fuzzy buffers with leader b +nnoremap b :Buffers +" Open grep +nnoremap g :FzfRg +" Open grep for cursor word +nnoremap c :FzfRg +" Close the current buffer +nnoremap x :bd +" Close all buffers +nnoremap z :%bd +" Alternate file navigation +nnoremap a :A +" Alternate file navigation vertical split +nnoremap v :AV +" Cycle line number modes +nnoremap r :call CycleNumbering() +" Open project +nnoremap m :call ToggleProject() +" Open scratch term +nnoremap s :call ToggleScratchTerm() +" Open lazygit +nnoremap ' :call ToggleLazyGit() +" Open vifm +nnoremap / :Vifm +" Get outline +nnoremap co :CocList outline +" Get symbols +nnoremap cs :CocList -I symbols +" Get errors +nnoremap cl :CocList locationlist +" Get available commands +nnoremap cc :CocList commands +" Restart server +nnoremap cR :CocRestart +" Quit term buffer with ESC +tnoremap +" Go to definition +nnoremap gd (coc-definition) +" Go to type definition +nnoremap gy (coc-type-definition) +" Go to implementation +nnoremap gi (coc-implementation) +" Find references +nnoremap gr (coc-references) +" Get hint +nnoremap gh :call CocActionAsync('doHover') + +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" vim-autopep8 +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +"let g:autopep8_disable_show_diff=1 +nnoremap :autopep8 + +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" airline +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +let g:airline_powerline_fonts = 1 +let g:airline_theme = 'tomorrow' + +" There needs to be a "fbgrep" command present in the home directory for this +" to work properly. If it doesn't exist, then we can back it up to using +" ack, or silver surfer. +set grepprg=rg +if filereadable(expand("~/bin/fbgrep")) + set grepprg=~/bin/fbgrep +endif +" bind K to grep word under cursor +nnoremap K :grep! "":cw + +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" Custom Functions +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" Creates a floating window with a most recent buffer to be used +function! CreateCenteredFloatingWindow() + let width = float2nr(&columns * 0.6) + let height = float2nr(&lines * 0.6) + let top = ((&lines - height) / 2) - 1 + let left = (&columns - width) / 2 + let opts = {'relative': 'editor', 'row': top, 'col': left, 'width': width, 'height': height, 'style': 'minimal'} + + let top = "╭" . repeat("─", width - 2) . "╮" + let mid = "│" . repeat(" ", width - 2) . "│" + let bot = "╰" . repeat("─", width - 2) . "╯" + let lines = [top] + repeat([mid], height - 2) + [bot] + let s:buf = nvim_create_buf(v:false, v:true) + call nvim_buf_set_lines(s:buf, 0, -1, v:true, lines) + call nvim_open_win(s:buf, v:true, opts) + set winhl=Normal:Floating + let opts.row += 1 + let opts.height -= 2 + let opts.col += 2 + let opts.width -= 4 + call nvim_open_win(nvim_create_buf(v:false, v:true), v:true, opts) + autocmd BufWipeout exe 'bwipeout '.s:buf + tnoremap :bw! +endfunction + +" Cycle through relativenumber + number, number (only), and no numbering. +function! CycleNumbering() abort + if exists('+relativenumber') + execute { + \ '00': 'set relativenumber | set number', + \ '01': 'set norelativenumber | set number', + \ '10': 'set norelativenumber | set nonumber', + \ '11': 'set norelativenumber | set number' }[&number . &relativenumber] + else + " No relative numbering, just toggle numbers on and off. + set number! + endif +endfunction + diff --git a/webapp.yml b/webapp.yml new file mode 100644 index 0000000..dc65148 --- /dev/null +++ b/webapp.yml @@ -0,0 +1,12 @@ +--- +- name: Configure yttrx webapp environment + hosts: [webapp] + roles: + - role: webapp + + handlers: + - name: Re-up docker containers + command: docker-compose up -d + args: + chdir: /home/mastodon/live + listen: "docker-compose up" diff --git a/yttrx.yml b/yttrx.yml new file mode 100644 index 0000000..69a50e7 --- /dev/null +++ b/yttrx.yml @@ -0,0 +1,6 @@ +--- +- name: Configure yttrx server environment + hosts: [yttrx] + roles: + - role: yttrx +