Compare commits

..

5 Commits

9 changed files with 107 additions and 37 deletions

View File

@ -190,6 +190,7 @@ bigbluebutton_enable_greenlight: "true"
#### Listmonk #### Listmonk
listmonk_admin_username: "admin" listmonk_admin_username: "admin"
listmonk_public_api_activated: False # Security hole. Can be used for spaming
#### Mastodon #### Mastodon
mastodon_version: "latest" mastodon_version: "latest"

View File

@ -0,0 +1,3 @@
location /api/public/subscription {
return 403;
}

View File

@ -2,6 +2,15 @@
- name: "include docker/compose/database.yml" - name: "include docker/compose/database.yml"
include_tasks: docker/compose/database.yml include_tasks: docker/compose/database.yml
- name: Set nginx_docker_reverse_proxy_extra_configuration based on listmonk_public_api_activated
set_fact:
nginx_docker_reverse_proxy_extra_configuration: >-
{% if not listmonk_public_api_activated %}
{{ lookup('file', '{{ role_path }}/files/deactivate-public-api.conf') }}
{% else %}
""
{% endif %}
- name: "include tasks nginx-docker-proxy-domain.yml" - name: "include tasks nginx-docker-proxy-domain.yml"
include_tasks: nginx-docker-proxy-domain.yml include_tasks: nginx-docker-proxy-domain.yml

View File

@ -9,8 +9,9 @@ address = "0.0.0.0:9000"
# be replaced with a better multi-user, role-based authentication system. # be replaced with a better multi-user, role-based authentication system.
# IMPORTANT: Leave both values empty to disable authentication on admin # IMPORTANT: Leave both values empty to disable authentication on admin
# only where an external authentication is already setup. # only where an external authentication is already setup.
admin_username = "{{listmonk_admin_username}}" # admin_username = "{{listmonk_admin_username}}"
admin_password = "{{listmonk_admin_password}}" # admin_password = "{{listmonk_admin_password}}"
# Deactivated for newer versions
# Database. # Database.
[db] [db]

View File

@ -14,8 +14,9 @@ This guide provides instructions for setting up, operating, and maintaining the
- [Debugging](#debugging) - [Debugging](#debugging)
- [Testing](#testing) - [Testing](#testing)
- [Updates](#updates) - [Updates](#updates)
- [Queue Management](#queue-management)
- [Spam Issues](#spam-issues)
- [To-Do](#to-do) - [To-Do](#to-do)
- [Spam Issues][#spam-issues]
- [References](#references) - [References](#references)
## Setup ## Setup
@ -26,7 +27,7 @@ Fetchmail might not work properly with large amounts of data. For more informati
#### Deactivating Fetchmail #### Deactivating Fetchmail
Before uninstalling Fetchmail, ensure to remove all fetched accounts from the administration panel. Before uninstalling Fetchmail, ensure you remove all fetched accounts from the administration panel.
#### Fetchmail Security Concerns #### Fetchmail Security Concerns
@ -114,8 +115,6 @@ docker-compose exec -it smtp postqueue -f
Use the following tools for testing: Use the following tools for testing:
- SSL-Tools Mailserver Test (URL: https://de.ssl-tools.net/mailservers/) - SSL-Tools Mailserver Test (URL: https://de.ssl-tools.net/mailservers/)
- TestEmail.de (URL: http://testemail.de/) - TestEmail.de (URL: http://testemail.de/)
@ -123,24 +122,43 @@ Use the following tools for testing:
For instructions on updating your Mailu setup, follow the official [Mailu maintenance guide](https://mailu.io/master/maintain.html). For instructions on updating your Mailu setup, follow the official [Mailu maintenance guide](https://mailu.io/master/maintain.html).
## Queue Management
To manage the Postfix email queue in Mailu, you can use the following commands:
- **Display the email queue**: This command shows all queued emails.
```bash
docker compose exec -it smtp postqueue -p
```
- **Delete all emails in the queue**: To remove all queued emails permanently, use the command:
```bash
docker compose exec -it smtp postsuper -d ALL
```
These commands can help control the email queue, especially for clearing out emails with delivery issues or delays.
## Spam Issues ## Spam Issues
### Inspect ### Inspect
To inspect use: Use the following tools to monitor your domain and email deliverability:
- [Google Postmaster](https://postmaster.google.com/)
- [Yahoo Postmaster](https://postmaster.yahooinc.com)
### Blacklisted - [Google Postmaster](https://postmaster.google.com/) - Analyzes deliverability and spam issues for Gmail.
It may be that your domain is blacklisted. In this case check out: - [Yahoo Postmaster](https://postmaster.yahooinc.com) - Provides insights and delivery reports for Yahoo.
- [Spamhaus](https://check.spamhaus.org/) ### Blacklist Check
- [Barracuda](https://www.barracudacentral.org/lookups)
### Reset If your domain is blacklisted, you can check the status with these services and take steps to remove your domain if necessary:
- [Cloudmark](https://csi.cloudmark.com/en/reset/)
- [Spamhaus](https://check.spamhaus.org/) - One of the most widely used blacklists for spam.
- [Barracuda](https://www.barracudacentral.org/lookups) - Checks if your IP is on the Barracuda blacklist.
### Cloudmark Reset Request
If your IP or domain is flagged by Cloudmark, you can submit a **reset request** to help restore deliverability:
- [Cloudmark Reset](https://csi.cloudmark.com/en/reset/)
## To-Do ## To-Do

View File

@ -32,9 +32,20 @@ After setting up mastodon you need to give the rights
docker-compose exec -it -u root web chown -R 991:991 public docker-compose exec -it -u root web chown -R 991:991 public
``` ```
### Running Database Migrations
To ensure all required database tables and structures are in place after an update, you can run database migrations directly within the Mastodon web container. Use the following command:
```bash
docker compose exec -it web bash -c "RAILS_ENV=production bin/rails db:migrate"
```
This command enters the web container and runs migrations in production mode, updating the database structure to match the current version of the Mastodon software. If your Mastodon web container is named differently in your `docker-compose.yml`, replace `web` with the appropriate container name.
## further information ## further information
- https://goneuland.de/mastodon-mit-docker-und-traefik-installieren/ - https://goneuland.de/mastodon-mit-docker-und-traefik-installieren/
- https://gist.github.com/TrillCyborg/84939cd4013ace9960031b803a0590c4 - https://gist.github.com/TrillCyborg/84939cd4013ace9960031b803a0590c4
- https://www.2daygeek.com/linux-command-check-website-is-up-down-alive/ - https://www.2daygeek.com/linux-command-check-website-is-up-down-alive/
- https://vitobotta.com/2022/11/07/setting-up-a-personal-mastodon-instance/ - https://vitobotta.com/2022/11/07/setting-up-a-personal-mastodon-instance/
- https://www.digitalocean.com/community/tutorials/how-to-scale-your-mastodon-server - https://www.digitalocean.com/community/tutorials/how-to-scale-your-mastodon-server

View File

@ -24,3 +24,7 @@ SMTP_AUTH_METHOD=plain
SMTP_OPENSSL_VERIFY_MODE=none SMTP_OPENSSL_VERIFY_MODE=none
SMTP_ENABLE_STARTTLS=auto SMTP_ENABLE_STARTTLS=auto
SMTP_FROM_ADDRESS=Mastodon <{{system_email_username}}> SMTP_FROM_ADDRESS=Mastodon <{{system_email_username}}>
ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY= {{mastodon_active_record_encryption_deterministic_key}}
ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT={{mastodon_active_record_encryption_key_derivation_salt}}
ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY={{mastodon_active_record_encryption_primary_key}}

View File

@ -21,7 +21,7 @@ services:
{% include 'templates/docker/container/networks.yml.j2' %} {% include 'templates/docker/container/networks.yml.j2' %}
streaming: streaming:
image: ghcr.io/mastodon/mastodon:{{mastodon_version}} image: ghcr.io/mastodon/mastodon-streaming:{{mastodon_version}}
restart: {{docker_restart_policy}} restart: {{docker_restart_policy}}
env_file: .env.production env_file: .env.production
command: node ./streaming command: node ./streaming

View File

@ -25,12 +25,6 @@ def run_command(command):
def git_pull(): def git_pull():
""" """
Checks whether the Git repository in the specified directory is up to date and performs a git pull if necessary. Checks whether the Git repository in the specified directory is up to date and performs a git pull if necessary.
Args:
directory (str): The path to the directory of the Git repository.
Returns:
bool: True if a git pull was performed, otherwise False.
""" """
print(f"Checking if the git repository is up to date.") print(f"Checking if the git repository is up to date.")
local = subprocess.check_output("git rev-parse @", shell=True).decode().strip() local = subprocess.check_output("git rev-parse @", shell=True).decode().strip()
@ -39,12 +33,15 @@ def git_pull():
if local != remote: if local != remote:
print("Repository is not up to date. Performing git pull.") print("Repository is not up to date. Performing git pull.")
run_command("git pull") run_command("git pull")
return True; return True
print("Repository is already up to date.") print("Repository is already up to date.")
return False; return False
def get_image_digests(directory): def get_image_digests(directory):
"""
Retrieves the image digests for all images in the specified Docker Compose project.
"""
compose_project = os.path.basename(directory) compose_project = os.path.basename(directory)
try: try:
images_output = subprocess.check_output( images_output = subprocess.check_output(
@ -59,16 +56,18 @@ def get_image_digests(directory):
raise # Other errors are still raised raise # Other errors are still raised
def is_any_service_up(): def is_any_service_up():
"""
Checks if any Docker services are currently running.
"""
process = subprocess.Popen("docker-compose ps -q", shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) process = subprocess.Popen("docker-compose ps -q", shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
output, _ = process.communicate() output, _ = process.communicate()
service_ids = output.decode().strip().splitlines() service_ids = output.decode().strip().splitlines()
return bool(service_ids)
# Check if there are any service containers up
if not service_ids:
return False # No services are up
return True # At least one service is up
def pull_docker_images(): def pull_docker_images():
"""
Pulls the latest Docker images for the project.
"""
print("Pulling docker images.") print("Pulling docker images.")
try: try:
run_command("docker-compose pull") run_command("docker-compose pull")
@ -82,13 +81,16 @@ def pull_docker_images():
return False return False
def update_docker(directory): def update_docker(directory):
"""
Checks for updates to Docker images and rebuilds containers if necessary.
"""
print(f"Checking for updates to Docker images in {directory}.") print(f"Checking for updates to Docker images in {directory}.")
before_digests = get_image_digests(directory) before_digests = get_image_digests(directory)
need_to_build = pull_docker_images() need_to_build = pull_docker_images()
after_digests = get_image_digests(directory) after_digests = get_image_digests(directory)
if before_digests != after_digests: if before_digests != after_digests:
print("Changes detected in image digests. Rebuilding containers.") print("Changes detected in image digests. Rebuilding containers.")
need_to_build=True need_to_build = True
if need_to_build: if need_to_build:
run_command("docker-compose build") run_command("docker-compose build")
@ -96,7 +98,18 @@ def update_docker(directory):
else: else:
print("Docker images are up to date. No rebuild necessary.") print("Docker images are up to date. No rebuild necessary.")
def update_mastodon():
"""
Runs the database migration for Mastodon to ensure all required tables are up to date.
"""
print("Starting Mastodon database migration.")
run_command("docker compose exec -T web bash -c 'RAILS_ENV=production bin/rails db:migrate'")
print("Mastodon database migration complete.")
def update_nextcloud(): def update_nextcloud():
"""
Performs the necessary Nextcloud update procedures, including maintenance and app updates.
"""
print("Start Nextcloud update procedure.") print("Start Nextcloud update procedure.")
update_procedure("docker-compose exec -T -u www-data application /var/www/html/occ upgrade") update_procedure("docker-compose exec -T -u www-data application /var/www/html/occ upgrade")
update_procedure("docker-compose exec -T -u www-data application /var/www/html/occ maintenance:repair") update_procedure("docker-compose exec -T -u www-data application /var/www/html/occ maintenance:repair")
@ -104,12 +117,17 @@ def update_nextcloud():
update_procedure("docker-compose exec -T -u www-data application /var/www/html/occ maintenance:mode --off") update_procedure("docker-compose exec -T -u www-data application /var/www/html/occ maintenance:mode --off")
def update_discourse(directory): def update_discourse(directory):
"""
Updates Discourse by running the rebuild command on the launcher script.
"""
os.chdir(directory) os.chdir(directory)
print("Start Discourse update procedure.") print("Start Discourse update procedure.")
update_procedure("./launcher rebuild app") update_procedure("./launcher rebuild app")
# This procedure waits until the container is up
def update_procedure(command): def update_procedure(command):
"""
Attempts to execute a command up to a maximum number of retries.
"""
max_attempts = 3 max_attempts = 3
for attempt in range(max_attempts): for attempt in range(max_attempts):
try: try:
@ -120,10 +138,13 @@ def update_procedure(command):
print(f"Attempt {attempt + 1} failed, retrying in 60 seconds...") print(f"Attempt {attempt + 1} failed, retrying in 60 seconds...")
time.sleep(60) # Wait for 60 seconds before retrying time.sleep(60) # Wait for 60 seconds before retrying
else: else:
print("All attempts to update Nextcloud apps have failed.") print("All attempts to update have failed.")
raise # Re-raise the last exception after all attempts fail raise # Re-raise the last exception after all attempts fail
def start_docker(directory): def start_docker(directory):
"""
Starts or restarts Docker services in the specified directory.
"""
if is_any_service_up(): if is_any_service_up():
print(f"Restarting containers in {directory}.") print(f"Restarting containers in {directory}.")
run_command("docker-compose up -d --force-recreate") run_command("docker-compose up -d --force-recreate")
@ -151,7 +172,7 @@ if __name__ == "__main__":
update_discourse(dir_path) update_discourse(dir_path)
else: else:
print("Discourse update skipped. No changes in git repository.") print("Discourse update skipped. No changes in git repository.")
if os.path.basename(dir_path) == "matrix": elif os.path.basename(dir_path) == "matrix":
# No autoupdate for matrix is possible atm, # No autoupdate for matrix is possible atm,
# due to the reason that the role has to be executed every time. # due to the reason that the role has to be executed every time.
# The update has to be executed in the role # The update has to be executed in the role
@ -164,3 +185,5 @@ if __name__ == "__main__":
# Nextcloud needs additional update procedures # Nextcloud needs additional update procedures
if os.path.basename(dir_path) == "nextcloud": if os.path.basename(dir_path) == "nextcloud":
update_nextcloud() update_nextcloud()
elif os.path.basename(dir_path) == "mastodon":
update_mastodon()