Compare commits

...

No commits in common. "37af4af588b3d6215138828c2c1c10381f2b51e5" and "a707d8a7462654390cbaea36ad0420820ddf16fe" have entirely different histories.

23 changed files with 668 additions and 5 deletions

20
LICENSE
View File

@ -1,9 +1,21 @@
MIT License
Copyright (c) 2023 PC-Admin
Copyright (c) 2023 Michael
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,3 +1,17 @@
# ansible-synapse
A ansible playbook to deploy a simple Synapse server. (For testing purposes only!)
A ansible playbook to deploy a simple Synapse server. (For testing purposes only!)
## Install Prerequisites
`$ pip install psycopg2`
## Setup Server
1) Configure the [inventory/](inventory/) files for all the desired hosts appropriately.
2) Run the setup.yml playbook:
`ansible-synapse$ ansible-playbook -v -i inventory/hosts setup.yml`

View File

@ -0,0 +1,11 @@
server_name: "penholder.xyz"
postgresql_password: "strong-redacted-password"
matrix_admin_email: "perthchat@protonmail.com"
registration_shared_secret: "strong-redacted-password"
testing_user: {
"username": "newuser2657",
"password": "strong-redacted-password",
"admin": True
}

View File

@ -0,0 +1,11 @@
server_name: "snowsupport.top"
postgresql_password: "strong-redacted-password"
matrix_admin_email: "perthchat@protonmail.com"
registration_shared_secret: "strong-redacted-password"
testing_user: {
"username": "newuser2657",
"password": "strong-redacted-password",
"admin": True
}

4
inventory/hosts Normal file
View File

@ -0,0 +1,4 @@
[matrix_servers]
#matrix.penholder.xyz ansible_host=matrix.penholder.xyz ansible_ssh_user=root
matrix.snowsupport.top ansible_host=matrix.snowsupport.top ansible_ssh_user=root

Binary file not shown.

6
roles/handlers/main.yml Normal file
View File

@ -0,0 +1,6 @@
---
- name: Restart Synapse
service:
name: matrix-synapse
state: restarted

View File

@ -0,0 +1,3 @@
- import_tasks: "{{ role_path }}/tasks/setup_redlight.yml"
tags: ['never', 'setup-redlight']

View File

@ -0,0 +1,63 @@
- name: Ensure /opt/synapse_modules directory exists
file:
path: /opt/synapse_modules
state: directory
owner: matrix-synapse
group: matrix-synapse
mode: '0755'
- name: Add PYTHONPATH to /lib/systemd/system/matrix-synapse.service file
lineinfile:
path: /lib/systemd/system/matrix-synapse.service
insertafter: "^[Service]"
regexp: '^Environment="PYTHONPATH=.*'
line: 'Environment="PYTHONPATH=$PYTHONPATH:/opt/synapse_modules"'
owner: root
group: root
mode: '0644'
- name: Reload systemd daemon
systemd:
daemon_reload: yes
- name: Ensure rsync is installed
apt:
name: rsync
state: present
- name: Clone redlight module to /tmp
git:
repo: https://code.glowers.club/PC-Admin/redlight.git
dest: /tmp/redlight
version: main
force: yes
- name: Synchronize /tmp/redlight content to /opt/synapse_modules/
synchronize:
src: /tmp/redlight/
dest: /opt/synapse_modules/
delete: yes
- name: Change ownership of /opt/synapse_modules/
file:
path: /opt/synapse_modules/
owner: matrix-synapse
group: matrix-synapse
recurse: yes
state: directory
- name: Add modules to homeserver.yaml
blockinfile:
path: /etc/matrix-synapse/homeserver.yaml
block: |
modules:
- module: hello_world_module.HelloWorldModule
config: {} # No specific configuration for this module
- module: abuse_lookup_module.AbuseLookupModule
config: {}
state: present
owner: root
group: root
mode: '0644'
notify: Restart Synapse

View File

@ -0,0 +1,11 @@
---
- name: Restart Synapse
service:
name: matrix-synapse
state: restarted
- name: Restart Nginx
service:
name: nginx
state: restarted

View File

@ -0,0 +1,34 @@
---
- name: Install Certbot
apt:
name: certbot
state: present
- name: Install Certbot Nginx Plugin
apt:
name: python3-certbot-nginx
state: present
- name: Create TLS certificate
become: yes
become_user: root
command: certbot certonly --rsa-key-size 2048 -d {{ server_name }} -d element.{{ server_name }} -d turn.{{ server_name }} --agree-tos --non-interactive --email {{ matrix_admin_email }} --nginx
- name: Setup SSL Auto-renewal
become: yes
become_user: root
cron:
name: certbot renew
minute: 0
hour: 0
day: 1
month: '*'
weekday: '*'
job: certbot renew --rsa-key-size 2048 --quiet --post-hook "systemctl reload nginx"
- name: Create Diffie-Hellman key
become: yes
become_user: root
command:
cmd: openssl dhparam -out /etc/letsencrypt/live/{{ server_name }}/dhparam2048.pem 2048
creates: /etc/letsencrypt/live/{{ server_name }}/dhparam2048.pem

View File

@ -0,0 +1,30 @@
---
- name: Install NGINX
apt:
name: nginx
state: present
- name: Configure Nginx Config for Matrix Synapse
template:
src: nginx.conf.j2
dest: "/etc/nginx/sites-available/{{ server_name }}"
mode: '0644'
notify: Restart Nginx
- name: Create a Symbolic Link for Nginx Config
file:
src: "/etc/nginx/sites-available/{{ server_name }}"
dest: "/etc/nginx/sites-enabled/{{ server_name }}"
state: link
- name: Remove default Nginx Config
file:
path: /etc/nginx/sites-enabled/default
state: absent
notify: Restart Nginx
- name: Remove 'matrix' Nginx Config
file:
path: /etc/nginx/sites-enabled/matrix
state: absent
notify: Restart Nginx

View File

@ -0,0 +1,37 @@
---
- name: Apply the homeserver.yaml template
template:
src: templates/homeserver.yaml.j2
dest: /etc/matrix-synapse/homeserver.yaml
owner: root
group: root
mode: '0644'
- name: Apply the nginx.conf template
template:
src: templates/nginx.conf.j2
dest: /etc/nginx/sites-available/matrix
owner: root
group: root
mode: '0644'
- name: Enable the nginx site
file:
src: /etc/nginx/sites-available/matrix
dest: /etc/nginx/sites-enabled/matrix
state: link
- name: Remove the default nginx site
file:
path: /etc/nginx/sites-enabled/default
state: absent
notify: Restart Nginx
# - name: Set Synapse Cache Factor
# lineinfile:
# path: /etc/default/matrix-synapse
# regexp: '^SYNAPSE_CACHE_FACTOR='
# line: 'SYNAPSE_CACHE_FACTOR=2.0'
# state: present
# create: yes
# notify: Restart Synapse

View File

@ -0,0 +1,4 @@
- name: Create Testing User
shell: |
sudo -u matrix-synapse python3 /opt/venvs/matrix-synapse/lib/python3.11/site-packages/synapse/_scripts/register_new_matrix_user.py -c /etc/matrix-synapse/homeserver.yaml http://localhost:8008 --user {{ testing_user.username }} --password {{ testing_user.password }}

View File

@ -0,0 +1,112 @@
---
- name: Template NGINX config for Element
become: yes
template:
src: "{{ role_path }}/templates/nginx-element.conf.j2"
dest: "/etc/nginx/sites-available/element"
owner: root
group: root
mode: '0644'
notify: Restart Nginx
- name: Create symbolic link for NGINX config
become: yes
file:
src: /etc/nginx/sites-available/element
dest: /etc/nginx/sites-enabled/element
state: link
force: yes
- name: Create the /var/www/element.penholder.xyz/ directory
become: yes
file:
path: "/var/www/element.{{ server_name}}"
state: directory
owner: root
group: root
mode: '0755'
- name: Download and install latest Element
become: yes
block:
- name: Install GPG
apt:
name: gnupg
state: present
- name: Copy Element release key to /tmp
copy:
src: "{{ playbook_dir }}/pubkey/element-release-key.gpg"
dest: /tmp/element-release-key.gpg
mode: '0644'
# need to install GPG key from https://packages.element.io/element-release-key.gpg
- name: Import Element release key
shell: gpg --import /tmp/element-release-key.gpg
- name: Download Element archive
get_url:
url: "https://github.com/vector-im/element-web/releases/download/v1.11.38/element-v1.11.38.tar.gz"
dest: "/tmp/element-v1.11.38.tar.gz"
- name: Download Element archive signature
get_url:
url: "https://github.com/vector-im/element-web/releases/download/v1.11.38/element-v1.11.38.tar.gz.asc"
dest: "/tmp/element-v1.11.38.tar.gz.asc"
- name: Verify Element archive signature
shell: gpg --verify /tmp/element-v1.11.38.tar.gz.asc /tmp/element-v1.11.38.tar.gz
args:
chdir: "/tmp"
- name: Extract Element archive
unarchive:
src: "/tmp/element-v1.11.38.tar.gz"
dest: "/tmp/"
remote_src: yes
args:
creates: "/var/www/element.{{ server_name}}/element-v1.11.38"
# Copy
# /tmp/element-v1.11.38/*
# /var/www/element.penholder.xyz/
- name: Copy Element files to web directory
shell: cp -r /tmp/element-v1.11.38/* /var/www/element.{{ server_name}}
args:
creates: "/var/www/element.{{ server_name}}/welcome.html"
- name: Clean up downloaded files
file:
path: "/tmp/element-v*"
state: absent
- name: Template the Element Config file
template:
src: "{{ role_path }}/templates/element.json.j2"
dest: "/var/www/element.{{ server_name}}/config.json"
owner: root
group: root
mode: '0644'
notify: Restart Nginx
# - name: Create and edit config.json for Element
# become: yes
# blockinfile:
# path: "/var/www/element.{{ server_name}}/config.json"
# create: yes
# content: |
# {
# "default_server_config": {
# "m.homeserver": {
# "base_url": "https://{{ server_name}}",
# "server_name": "{{ server_name}}"
# },
# "m.identity_server": {
# "base_url": "https://vector.im"
# }
# },
# # ... (other config options)
# }

View File

@ -0,0 +1,39 @@
---
- name: Install Postgresql
apt:
name: "{{ item }}"
state: present
loop:
- postgresql
- postgresql-client
- name: Ensure pip is installed
apt:
name: python3-pip
state: present
- name: Install psycopg2 with pip
pip:
name: psycopg2-binary
state: present
extra_args: "{{ (ansible_distribution == 'Debian' and ansible_distribution_version is version('12', '>=')) | ternary('--break-system-packages', '') }}"
- name: Create Synapse role in PostgreSQL
become: yes
become_user: postgres
postgresql_user:
name: synapse
password: "{{ postgresql_password }}"
role_attr_flags: NOSUPERUSER,NOCREATEDB,NOCREATEROLE
encrypted: yes
- name: Create Database for Synapse
become: yes
become_user: postgres
postgresql_db:
name: synapse
encoding: UTF8
lc_collate: C
lc_ctype: C
template: template0
owner: synapse

View File

@ -0,0 +1,83 @@
---
# sudo apt update
- name: Update apt cache
apt:
update_cache: yes
#sudo apt install -y lsb-release wget apt-transport-https
- name: Install Prerequisite Packages
apt:
name: "{{ item }}"
state: present
loop:
- lsb-release
- wget
- apt-transport-https
#sudo wget -O /usr/share/keyrings/matrix-org-archive-keyring.gpg https://packages.matrix.org/debian/matrix-org-archive-keyring.gpg
#echo "deb [signed-by=/usr/share/keyrings/matrix-org-archive-keyring.gpg] https://packages.matrix.org/debian/ $(lsb_release -cs) main" |
# sudo tee /etc/apt/sources.list.d/matrix-org.list
- name: Download Matrix.org GPG keyring
get_url:
url: https://packages.matrix.org/debian/matrix-org-archive-keyring.gpg
dest: /usr/share/keyrings/matrix-org-archive-keyring.gpg
mode: '0644'
- name: Add Matrix.org repository
apt_repository:
repo: deb [signed-by=/usr/share/keyrings/matrix-org-archive-keyring.gpg] https://packages.matrix.org/debian/ {{ ansible_distribution_release }} main
state: present
#sudo apt update
- name: Update apt cache
apt:
update_cache: yes
#sudo apt install matrix-synapse-py3
- name: Install Synapse
apt:
name: matrix-synapse-py3
state: present
# sudo systemctl stop matrix-synapse
- name: Stop Synapse
service:
name: matrix-synapse
state: stopped
- name: Ensure /var/lib/matrix-synapse/media directory exists
file:
path: /var/lib/matrix-synapse/media
state: directory
owner: matrix-synapse
group: matrix-synapse
mode: '0755'
- name: Add server_name to /etc/matrix-synapse/conf.d/server_name.yaml file
lineinfile:
path: /etc/matrix-synapse/conf.d/server_name.yaml
regexp: '^server_name:.*'
line: "server_name: {{ server_name }}"
create: yes
owner: root
group: root
mode: '0644'
# Write "{{ registration_shared_secret }}" to /etc/matrix-synapse/conf.d/registration_shared_secret.yaml
- name: Write registration_shared_secret to /etc/matrix-synapse/conf.d/registration_shared_secret.yaml
lineinfile:
path: /etc/matrix-synapse/conf.d/registration_shared_secret.yaml
regexp: '^registration_shared_secret:.*'
line: "registration_shared_secret: {{ registration_shared_secret }}"
create: yes
owner: root
group: root
mode: '0644'

View File

@ -0,0 +1,23 @@
# Install Synapse
- import_tasks: "{{ role_path }}/tasks/install_synapse.yml"
# Install Postgresql
- import_tasks: "{{ role_path }}/tasks/install_postgresql.yml"
# Certbot Setup
- import_tasks: "{{ role_path }}/tasks/certbot_setup.yml"
# Configure Nginx
- import_tasks: "{{ role_path }}/tasks/config_nginx.yml"
# Configure Synapse
- import_tasks: "{{ role_path }}/tasks/config_synapse.yml"
# Install Element Web
- import_tasks: "{{ role_path }}/tasks/element_setup.yml"
tags: install-element
# Create Admin User
- import_tasks: "{{ role_path }}/tasks/create_admin_user.yml"
tags: create-admin-user

View File

@ -0,0 +1,48 @@
{
"default_server_config": {
"m.homeserver": {
"base_url": "https://{{ server_name }}",
"server_name": "{{ server_name }}"
},
"m.identity_server": {
"base_url": "https://vector.im"
}
},
"disable_custom_urls": false,
"disable_guests": false,
"disable_login_language_selector": false,
"disable_3pid_login": false,
"brand": "Element",
"integrations_ui_url": "https://scalar.vector.im/",
"integrations_rest_url": "https://scalar.vector.im/api",
"integrations_widgets_urls": [
"https://scalar.vector.im/_matrix/integrations/v1",
"https://scalar.vector.im/api",
"https://scalar-staging.vector.im/_matrix/integrations/v1",
"https://scalar-staging.vector.im/api",
"https://scalar-staging.riot.im/scalar/api"
],
"default_country_code": "GB",
"show_labs_settings": false,
"features": {},
"default_federate": true,
"default_theme": "light",
"room_directory": {
"servers": ["{{ server_name }}"]
},
"enable_presence_by_hs_url": {
"https://{{ server_name }}": false
},
"setting_defaults": {
"breadcrumbs": true
},
"jitsi": {
"preferred_domain": "meet.element.io"
},
"element_call": {
"url": "https://call.element.io",
"participant_limit": 8,
"brand": "Element Call"
},
"map_style_url": "https://api.maptiler.com/maps/streets/style.json?key=fU3vlMsMn4Jb6dnEIFsx"
}

View File

@ -0,0 +1,33 @@
server_name: "{{ server_name }}"
pid_file: "/var/run/matrix-synapse.pid"
listeners:
- port: 8008
tls: false
type: http
x_forwarded: true
bind_addresses: ['::1', '127.0.0.1']
resources:
- names: [client, federation]
compress: false
database:
name: psycopg2
args:
user: synapse
password: "{{ postgresql_password }}"
database: synapse
host: localhost
cp_min: 5
cp_max: 10
log_config: "/etc/matrix-synapse/log.yaml"
media_store_path: "/var/lib/matrix-synapse/media"
signing_key_path: "/etc/matrix-synapse/homeserver.signing.key"
trusted_key_servers:
- server_name: "matrix.org"
web_client_location: "https://element.{{ server_name }}/"
federation_client_minimum_tls_version: 1.2
allow_public_rooms_over_federation: true
enable_registration: false
admin_contact: "mailto:{{ matrix_admin_email }}"
registration_shared_secret: "{{ registration_shared_secret }}"
caches:
global_factor: 1.0

View File

@ -0,0 +1,31 @@
server {
listen 80;
server_name element.{{ server_name }};
return 301 https://element.{{ server_name }}$request_uri;
}
server {
listen 443 ssl http2;
gzip off;
server_name element.{{ server_name }};
ssl_certificate /etc/letsencrypt/live/{{ server_name }}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/{{ server_name }}/privkey.pem;
ssl_session_cache shared:NGX_SSL_CACHE:10m;
ssl_session_timeout 12h;
ssl_protocols TLSv1.3 TLSv1.2;
ssl_ciphers "TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-256-GCM-SHA384:TLS13-AES-128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256";
ssl_dhparam /etc/letsencrypt/live/{{ server_name }}/dhparam2048.pem;
ssl_ecdh_curve X25519:secp521r1:secp384r1:prime256v1;
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains" always;
add_header X-Content-Type-Options "nosniff" always;
root /var/www/element.{{ server_name }};
index index.html;
location / {
try_files $uri $uri/ =404;
}
}

View File

@ -0,0 +1,46 @@
server {
listen 80;
server_name {{ server_name }};
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
listen 8448 ssl http2; # for federation (skip if pointing SRV or .well-known to port 443)
gzip off;
server_name {{ server_name }};
ssl_certificate "/etc/letsencrypt/live/{{ server_name }}/fullchain.pem";
ssl_certificate_key "/etc/letsencrypt/live/{{ server_name }}/privkey.pem";
ssl_session_cache shared:NGX_SSL_CACHE:10m;
ssl_session_timeout 12h;
ssl_protocols TLSv1.3 TLSv1.2;
ssl_ciphers "TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-256-GCM-SHA384:TLS13-AES-128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256";
ssl_dhparam "/etc/letsencrypt/live/{{ server_name }}/dhparam2048.pem";
ssl_ecdh_curve X25519:secp521r1:secp384r1:prime256v1;
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains" always;
add_header X-Content-Type-Options "nosniff" always;
location / {
return 301 https://element.{{ server_name }};
}
location /_matrix {
proxy_pass http://127.0.0.1:8008;
proxy_set_header X-Forwarded-For $remote_addr;
}
# This can be skipped if you're using port 8448 on {{ server_name }} for federation:
location /.well-known/matrix/server {
return 200 '{ "m.server": "{{ server_name }}:8448" }';
add_header content-type application/json;
}
location /.well-known/matrix/client {
return 200 '{ "m.homeserver": { "base_url": "https://{{ server_name }}" }, "im.vector.riot.jitsi": { "preferredDomain": "jitsi.riot.im" } }';
add_header access-control-allow-origin *;
add_header content-type application/json;
}
}

8
setup.yml Normal file
View File

@ -0,0 +1,8 @@
- name: "Creates a basic Synapse server."
hosts: matrix_servers
gather_facts: true
roles:
- setup-synapse
- setup-redlight