commit da0f53a470734ef19b893034b6a36daf753e9e70 Author: Your Name Date: Wed Oct 22 08:24:36 2025 -0600 Initial AnonAddy Cloudron package diff --git a/CloudronManifest.json b/CloudronManifest.json new file mode 100644 index 0000000..abc608d --- /dev/null +++ b/CloudronManifest.json @@ -0,0 +1,28 @@ +{ + "id": "org.anonaddy.cloudron", + "title": "AnonAddy", + "author": "AnonAddy Team", + "description": "Anonymous email forwarding service that lets you create unlimited email aliases to protect your real email address from spam and tracking.", + "tagline": "Anonymous email forwarding", + "version": "1.3.5", + "healthCheckPath": "/", + "httpPort": 8000, + "addons": { + "localstorage": {}, + "mysql": {}, + "redis": {}, + "sendmail": {} + }, + "manifestVersion": 2, + "website": "https://anonaddy.com", + "contactEmail": "support@anonaddy.com", + "minBoxVersion": "7.0.0", + "maxBoxVersion": "8.0.0", + "mediaLinks": [ + "https://anonaddy.com/assets/img/logo.svg" + ], + "postInstallMessage": "AnonAddy is now installed!\n\nIMPORTANT SETUP STEPS:\n\n1. Login with the default admin credentials:\n Email: admin@example.com\n Password: password\n\n2. IMMEDIATELY change the admin password in Settings\n\n3. Configure your domain in Settings -> Domains\n\n4. Set up DNS records:\n - MX record pointing to your Cloudron server\n - SPF record for email authentication\n - DKIM keys (generated in Settings)\n\n5. Configure SMTP settings to receive emails\n\nFor more information, visit: https://anonaddy.com/help", + "icon": "file://logo.png", + "memoryLimit": 512000000, + "optionalSso": true +} diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..8082063 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,96 @@ +FROM cloudron/base:5.0.0 + +# Install dependencies +RUN apt-get update && \ + apt-get install -y \ + php8.3 \ + php8.3-cli \ + php8.3-fpm \ + php8.3-mysql \ + php8.3-redis \ + php8.3-curl \ + php8.3-gd \ + php8.3-mbstring \ + php8.3-xml \ + php8.3-zip \ + php8.3-bcmath \ + php8.3-intl \ + php8.3-gnupg \ + php8.3-gmp \ + php8.3-imagick \ + php8.3-mailparse \ + composer \ + nginx \ + supervisor \ + postfix \ + rspamd \ + redis-tools \ + mysql-client \ + gnupg \ + git \ + curl \ + nodejs \ + npm && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +# Set working directory +WORKDIR /app/code + +# Clone AnonAddy repository +RUN git clone --branch v1.3.5 https://github.com/anonaddy/anonaddy.git /app/code && \ + chown -R cloudron:cloudron /app/code + +# Install PHP dependencies +RUN cd /app/code && \ + composer install --no-dev --optimize-autoloader --no-interaction && \ + chown -R cloudron:cloudron /app/code/vendor + +# Install Node dependencies and build assets +RUN cd /app/code && \ + npm install && \ + npm run prod && \ + rm -rf node_modules && \ + chown -R cloudron:cloudron /app/code/public + +# Copy configuration files +COPY nginx.conf /etc/nginx/sites-available/default +COPY supervisor.conf /etc/supervisor/conf.d/anonaddy.conf +COPY start.sh /app/code/start.sh +COPY postfix-main.cf /tmp/postfix-main.cf +COPY postfix-master.cf /tmp/postfix-master.cf + +# Initialize data directory structure +RUN mkdir -p /tmp/data && \ + mkdir -p /tmp/data/storage && \ + mkdir -p /tmp/data/storage/logs && \ + mkdir -p /tmp/data/storage/framework && \ + mkdir -p /tmp/data/storage/framework/cache && \ + mkdir -p /tmp/data/storage/framework/sessions && \ + mkdir -p /tmp/data/storage/framework/views && \ + mkdir -p /tmp/data/storage/app && \ + mkdir -p /tmp/data/storage/app/public && \ + mkdir -p /tmp/data/dkim && \ + mkdir -p /tmp/data/postfix && \ + mkdir -p /tmp/data/rspamd && \ + chown -R cloudron:cloudron /tmp/data + +# Set permissions +RUN chmod +x /app/code/start.sh && \ + chown -R cloudron:cloudron /app/code && \ + chmod -R 755 /app/code/storage && \ + chmod -R 755 /app/code/bootstrap/cache + +# Configure PHP-FPM to run as cloudron user +RUN sed -i 's/user = www-data/user = cloudron/g' /etc/php/8.3/fpm/pool.d/www.conf && \ + sed -i 's/group = www-data/group = cloudron/g' /etc/php/8.3/fpm/pool.d/www.conf && \ + sed -i 's/listen.owner = www-data/listen.owner = cloudron/g' /etc/php/8.3/fpm/pool.d/www.conf && \ + sed -i 's/listen.group = www-data/listen.group = cloudron/g' /etc/php/8.3/fpm/pool.d/www.conf + +# Configure PHP to log to stderr +RUN sed -i 's/;catch_workers_output = yes/catch_workers_output = yes/g' /etc/php/8.3/fpm/pool.d/www.conf && \ + sed -i 's/;php_admin_flag[log_errors] = on/php_admin_flag[log_errors] = on/g' /etc/php/8.3/fpm/pool.d/www.conf + +EXPOSE 8000 25 + +CMD ["/app/code/start.sh"] diff --git a/README.md b/README.md new file mode 100644 index 0000000..fefe02e --- /dev/null +++ b/README.md @@ -0,0 +1,297 @@ +# AnonAddy Cloudron Package + +This is a complete Cloudron package for [AnonAddy](https://anonaddy.com), an open-source anonymous email forwarding service. + +## Features + +- Anonymous email forwarding with unlimited aliases +- Custom domain support +- GPG/OpenPGP email encryption +- Reply anonymously without revealing your real email +- MySQL database for data storage +- Redis for caching and queues +- Postfix for SMTP email handling +- Rspamd for spam filtering +- Laravel queue worker for background jobs +- Automatic database migrations + +## Package Contents + +- `CloudronManifest.json` - Cloudron package manifest +- `Dockerfile` - Container image definition +- `start.sh` - Initialization and startup script +- `nginx.conf` - NGINX web server configuration +- `supervisor.conf` - Process supervisor configuration +- `postfix-main.cf` - Postfix main configuration +- `postfix-master.cf` - Postfix master process configuration + +## Prerequisites + +1. Cloudron CLI installed and configured +2. Docker access (handled by Cloudron build service) +3. Cloudron instance running version 7.0.0 or higher +4. Domain with proper DNS configuration + +## Building the Package + +Build the package using the Cloudron build service: + +```bash +cloudron build \ + --set-build-service builder.docker.due.ren \ + --build-service-token e3265de06b1d0e7bb38400539012a8433a74c2c96a17955e \ + --set-repository andreasdueren/anonaddy-cloudron \ + --tag 0.1.0 +``` + +The build process will: +1. Create a Docker image based on cloudron/base:5.0.0 +2. Install PHP 8.3, NGINX, Postfix, Rspamd, and other dependencies +3. Clone AnonAddy v1.3.5 from GitHub +4. Install Composer dependencies +5. Build frontend assets +6. Configure all services + +## Installation + +Install the package on your Cloudron instance: + +```bash +cloudron install \ + --location anonaddy.yourdomain.com \ + --image andreasdueren/anonaddy-cloudron:0.1.0 +``` + +Replace `anonaddy.yourdomain.com` with your desired subdomain. + +## Post-Installation Setup + +### 1. Initial Login + +After installation, you'll see a post-install message with default credentials: + +- Email: `admin@example.com` +- Password: `password` + +**IMPORTANT:** Change this password immediately after first login! + +### 2. DNS Configuration + +Configure the following DNS records for your domain: + +#### MX Record +``` +@ IN MX 10 anonaddy.yourdomain.com. +``` + +#### SPF Record +``` +@ IN TXT "v=spf1 mx ~all" +``` + +#### DKIM Keys +1. Login to AnonAddy +2. Navigate to Settings → DKIM +3. Generate DKIM keys +4. Add the provided DNS TXT record + +Example: +``` +default._domainkey IN TXT "v=DKIM1; k=rsa; p=YOUR_PUBLIC_KEY_HERE" +``` + +#### DMARC Record (Optional but recommended) +``` +_dmarc IN TXT "v=DMARC1; p=quarantine; rua=mailto:dmarc@yourdomain.com" +``` + +### 3. Configure Domain Settings + +1. Login to AnonAddy +2. Go to Settings → Domains +3. Add your custom domain(s) +4. Verify domain ownership + +### 4. Configure Email Recipients + +1. Add recipient email addresses (your real email addresses) +2. Verify recipient addresses via email confirmation +3. Set default recipient for new aliases + +## Usage + +### Creating Aliases + +AnonAddy supports multiple alias formats: + +1. **Standard Aliases:** `anything@yourdomain.com` +2. **UUID Aliases:** `94960540-f914-42e0-9c50-6fecbe7f5061@yourdomain.com` +3. **Custom Aliases:** `newsletter@yourdomain.com` + +### Replying Anonymously + +Reply to forwarded emails directly. AnonAddy will send the reply through the alias, maintaining your anonymity. + +### Encryption + +Enable GPG encryption in Settings to encrypt all incoming emails with your public key. + +## Architecture + +### Services + +The package runs multiple services via supervisor: + +- **NGINX** - Web server (port 8000) +- **PHP-FPM** - PHP processor +- **Laravel Queue Worker** - Background job processing +- **Laravel Scheduler** - Cron job handler +- **Postfix** - SMTP server (port 25) +- **Rspamd** - Spam filtering (port 11334) + +### Data Persistence + +All persistent data is stored in `/app/data`: + +- `/app/data/storage` - Laravel storage (logs, cache, sessions) +- `/app/data/dkim` - DKIM keys +- `/app/data/postfix` - Postfix spool +- `/app/data/rspamd` - Rspamd data +- `/app/data/app_key` - Laravel application key +- `/app/data/anonaddy_secret` - AnonAddy secret for anonymous replies + +### Database + +The package uses: +- **MySQL** - Main database (via Cloudron addon) +- **Redis** - Cache and queue backend (via Cloudron addon) + +### Email Integration + +- **Inbound:** Postfix receives emails on port 25 +- **Outbound:** Cloudron SMTP addon for sending emails +- **Spam Filtering:** Rspamd filters incoming emails +- **Virtual Aliases:** Postfix queries Rspamd for alias lookups + +## Troubleshooting + +### View Logs + +```bash +cloudron logs --app anonaddy.yourdomain.com -f +``` + +### Shell Access + +```bash +cloudron exec --app anonaddy.yourdomain.com +``` + +### Common Issues + +#### Emails Not Receiving + +1. Check MX records: `dig MX yourdomain.com` +2. Verify port 25 is open on your Cloudron server +3. Check Postfix logs: `cloudron logs --app anonaddy.yourdomain.com | grep postfix` +4. Test SMTP: `telnet anonaddy.yourdomain.com 25` + +#### Emails Marked as Spam + +1. Ensure SPF record is configured +2. Add DKIM keys in Settings +3. Configure DMARC record +4. Check your server's IP reputation + +#### Queue Not Processing + +1. Check Laravel queue worker: `cloudron logs --app anonaddy.yourdomain.com | grep queue` +2. Verify Redis connection +3. Restart the app: `cloudron restart --app anonaddy.yourdomain.com` + +#### Application Errors + +1. Check storage permissions in `/app/data/storage` +2. Clear cache: `cloudron exec --app anonaddy.yourdomain.com 'php artisan cache:clear'` +3. Run migrations: `cloudron exec --app anonaddy.yourdomain.com 'php artisan migrate'` + +### Database Migrations + +Migrations run automatically on startup. To manually run migrations: + +```bash +cloudron exec --app anonaddy.yourdomain.com +cd /app/code +php artisan migrate +``` + +### Clear Cache + +```bash +cloudron exec --app anonaddy.yourdomain.com +cd /app/code +php artisan cache:clear +php artisan config:clear +php artisan view:clear +``` + +## Updating + +To update to a new version: + +1. Build the new version with updated tag +2. Uninstall the old version: `cloudron uninstall --app anonaddy.yourdomain.com` +3. Install the new version: `cloudron install --location anonaddy.yourdomain.com --image andreasdueren/anonaddy-cloudron:NEW_VERSION` + +**Note:** Always backup your data before updating! + +## Development + +### Local Testing + +1. Clone the repository +2. Make changes to configuration files +3. Build locally: `cloudron build --tag test` +4. Install for testing: `cloudron install --location test.anonaddy.local --image andreasdueren/anonaddy-cloudron:test` + +### File Locations + +- Application code: `/app/code` +- Persistent data: `/app/data` +- NGINX config: `/etc/nginx/sites-available/default` +- PHP-FPM config: `/etc/php/8.3/fpm/pool.d/www.conf` +- Postfix config: `/etc/postfix/main.cf` +- Supervisor config: `/etc/supervisor/conf.d/anonaddy.conf` + +## Security Considerations + +1. **Change Default Password:** Immediately after installation +2. **HTTPS Only:** Cloudron automatically provides SSL/TLS +3. **SPF/DKIM/DMARC:** Configure all email authentication records +4. **Firewall:** Ensure only necessary ports (80, 443, 25) are open +5. **Updates:** Keep AnonAddy updated to latest version +6. **Backups:** Regular backups via Cloudron + +## Resources + +- [AnonAddy Website](https://anonaddy.com) +- [AnonAddy GitHub](https://github.com/anonaddy/anonaddy) +- [AnonAddy Documentation](https://anonaddy.com/help) +- [Cloudron Documentation](https://docs.cloudron.io) +- [Cloudron Packaging Guide](https://docs.cloudron.io/packaging/) + +## License + +AnonAddy is open-source software licensed under the MIT license. + +## Support + +For issues with: +- **AnonAddy application:** https://github.com/anonaddy/anonaddy/issues +- **Cloudron package:** https://git.due.ren/andreas/anonaddy.git +- **Cloudron platform:** https://forum.cloudron.io + +## Credits + +- AnonAddy by [Will Browning](https://github.com/willbrowningme) +- Cloudron package by Andreas Dueren diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 0000000..206fc0e --- /dev/null +++ b/nginx.conf @@ -0,0 +1,85 @@ +server { + listen 8000 default_server; + listen [::]:8000 default_server; + + server_name _; + + root /app/code/public; + index index.php index.html; + + # Logging to stdout/stderr + access_log /dev/stdout; + error_log /dev/stderr; + + # Security headers + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-Content-Type-Options "nosniff" always; + add_header X-XSS-Protection "1; mode=block" always; + add_header Referrer-Policy "strict-origin-when-cross-origin" always; + + # Client body size + client_max_body_size 25M; + + # Gzip compression + gzip on; + gzip_vary on; + gzip_proxied any; + gzip_comp_level 6; + gzip_types text/plain text/css text/xml text/javascript application/json application/javascript application/xml+rss application/rss+xml font/truetype font/opentype application/vnd.ms-fontobject image/svg+xml; + + location / { + try_files $uri $uri/ /index.php?$query_string; + } + + location = /favicon.ico { + access_log off; + log_not_found off; + } + + location = /robots.txt { + access_log off; + log_not_found off; + } + + # Deny access to hidden files + location ~ /\. { + deny all; + access_log off; + log_not_found off; + } + + # PHP-FPM configuration + location ~ \.php$ { + fastcgi_split_path_info ^(.+\.php)(/.+)$; + fastcgi_pass unix:/run/php/php8.3-fpm.sock; + fastcgi_index index.php; + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_param PATH_INFO $fastcgi_path_info; + fastcgi_param HTTP_PROXY ""; + + # Proxy headers for Cloudron + fastcgi_param HTTP_X_FORWARDED_FOR $proxy_add_x_forwarded_for; + fastcgi_param HTTP_X_FORWARDED_PROTO $scheme; + fastcgi_param HTTP_HOST $host; + + fastcgi_intercept_errors off; + fastcgi_buffer_size 16k; + fastcgi_buffers 4 16k; + fastcgi_connect_timeout 300; + fastcgi_send_timeout 300; + fastcgi_read_timeout 300; + } + + # Static files caching + location ~* \.(jpg|jpeg|gif|png|css|js|ico|xml|svg|woff|woff2|ttf|eot)$ { + expires 30d; + access_log off; + add_header Cache-Control "public, immutable"; + } + + # Deny access to sensitive files + location ~ /\.(?!well-known).* { + deny all; + } +} diff --git a/postfix-main.cf b/postfix-main.cf new file mode 100644 index 0000000..c1f445a --- /dev/null +++ b/postfix-main.cf @@ -0,0 +1,67 @@ +# Basic configuration +compatibility_level = 2 +smtpd_banner = $myhostname ESMTP +biff = no +append_dot_mydomain = no +readme_directory = no + +# TLS parameters +smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem +smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key +smtpd_use_tls=yes +smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache +smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache +smtpd_tls_security_level = may +smtp_tls_security_level = may +smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 +smtp_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 +smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 +smtp_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 + +# Network and domain settings +myhostname = CLOUDRON_APP_DOMAIN +myorigin = CLOUDRON_MAIL_DOMAIN +mydestination = CLOUDRON_APP_DOMAIN, localhost +relayhost = +mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 +mailbox_size_limit = 0 +recipient_delimiter = + +inet_interfaces = all +inet_protocols = all + +# Virtual alias domains +virtual_alias_domains = CLOUDRON_APP_DOMAIN +virtual_alias_maps = tcp:127.0.0.1:11334 + +# Queue and message settings +message_size_limit = 26214400 +mailbox_size_limit = 0 +maximal_queue_lifetime = 1d +bounce_queue_lifetime = 1d + +# Milter configuration for Rspamd +smtpd_milters = inet:127.0.0.1:11332 +non_smtpd_milters = inet:127.0.0.1:11332 +milter_protocol = 6 +milter_mail_macros = i {mail_addr} {client_addr} {client_name} {auth_authen} +milter_default_action = accept + +# SMTP restrictions +smtpd_recipient_restrictions = + permit_mynetworks, + reject_unauth_destination, + reject_non_fqdn_recipient, + reject_unknown_recipient_domain + +smtpd_helo_restrictions = + permit_mynetworks, + reject_invalid_helo_hostname, + reject_non_fqdn_helo_hostname + +smtpd_sender_restrictions = + permit_mynetworks, + reject_non_fqdn_sender, + reject_unknown_sender_domain + +# Logging +maillog_file = /dev/stdout diff --git a/postfix-master.cf b/postfix-master.cf new file mode 100644 index 0000000..2636e6e --- /dev/null +++ b/postfix-master.cf @@ -0,0 +1,41 @@ +# ========================================================================== +# service type private unpriv chroot wakeup maxproc command + args +# (yes) (yes) (no) (never) (100) +# ========================================================================== +smtp inet n - n - - smtpd +pickup unix n - n 60 1 pickup +cleanup unix n - n - 0 cleanup +qmgr unix n - n 300 1 qmgr +tlsmgr unix - - n 1000? 1 tlsmgr +rewrite unix - - n - - trivial-rewrite +bounce unix - - n - 0 bounce +defer unix - - n - 0 bounce +trace unix - - n - 0 bounce +verify unix - - n - 1 verify +flush unix n - n 1000? 0 flush +proxymap unix - - n - - proxymap +proxywrite unix - - n - 1 proxymap +smtp unix - - n - - smtp +relay unix - - n - - smtp +showq unix n - n - - showq +error unix - - n - - error +retry unix - - n - - error +discard unix - - n - - discard +local unix - n n - - local +virtual unix - n n - - virtual +lmtp unix - - n - - lmtp +anvil unix - - n - 1 anvil +scache unix - - n - 1 scache +maildrop unix - n n - - pipe + flags=DRhu user=vmail argv=/usr/bin/maildrop -d ${recipient} +uucp unix - n n - - pipe + flags=Fqhu user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient) +ifmail unix - n n - - pipe + flags=F user=ftn argv=/usr/lib/ifmail/ifmail -r $nexthop ($recipient) +bsmtp unix - n n - - pipe + flags=Fq. user=bsmtp argv=/usr/lib/bsmtp/bsmtp -t$nexthop -f$sender $recipient +scalemail-backend unix - n n - 2 pipe + flags=R user=scalemail argv=/usr/lib/scalemail/bin/scalemail-store ${nexthop} ${user} ${extension} +mailman unix - n n - - pipe + flags=FR user=list argv=/usr/lib/mailman/bin/postfix-to-mailman.py + ${nexthop} ${user} diff --git a/start.sh b/start.sh new file mode 100644 index 0000000..07a29a1 --- /dev/null +++ b/start.sh @@ -0,0 +1,150 @@ +#!/bin/bash +set -eu + +echo "==> Starting AnonAddy initialization" + +# Initialize /app/data if empty +if [ ! -d "/app/data/storage" ]; then + echo "==> Initializing /app/data from /tmp/data" + cp -r /tmp/data/* /app/data/ + chown -R cloudron:cloudron /app/data +fi + +# Ensure proper permissions +chown -R cloudron:cloudron /app/data +chmod -R 755 /app/data/storage + +# Link storage directory to Laravel storage +rm -rf /app/code/storage +ln -sf /app/data/storage /app/code/storage + +# Create .env file +echo "==> Configuring application environment" +cat > /app/code/.env < Generating application key" + cd /app/code + sudo -u cloudron php artisan key:generate --force + # Save the key to persistent storage + grep "APP_KEY=" /app/code/.env | cut -d= -f2 > /app/data/app_key +else + echo "==> Using existing application key" + APP_KEY=$(cat /app/data/app_key) + sed -i "s|APP_KEY=.*|APP_KEY=${APP_KEY}|g" /app/code/.env +fi + +# Generate ANONADDY_SECRET if it doesn't exist +if [ ! -f "/app/data/anonaddy_secret" ]; then + echo "==> Generating AnonAddy secret" + ANONADDY_SECRET=$(openssl rand -hex 32) + echo "$ANONADDY_SECRET" > /app/data/anonaddy_secret + echo "ANONADDY_SECRET=${ANONADDY_SECRET}" >> /app/code/.env +else + echo "==> Using existing AnonAddy secret" + ANONADDY_SECRET=$(cat /app/data/anonaddy_secret) + echo "ANONADDY_SECRET=${ANONADDY_SECRET}" >> /app/code/.env +fi + +# Set proper ownership +chown cloudron:cloudron /app/code/.env +chmod 640 /app/code/.env + +# Run database migrations +echo "==> Running database migrations" +cd /app/code +sudo -u cloudron php artisan migrate --force + +# Clear and cache configuration +echo "==> Optimizing application" +sudo -u cloudron php artisan config:clear +sudo -u cloudron php artisan cache:clear +sudo -u cloudron php artisan view:clear +sudo -u cloudron php artisan config:cache +sudo -u cloudron php artisan route:cache + +# Create default admin user if database is empty +USER_COUNT=$(sudo -u cloudron php artisan tinker --execute="echo \App\Models\User::count();") +if [ "$USER_COUNT" -eq "0" ]; then + echo "==> Creating default admin user" + sudo -u cloudron php artisan tinker <username = 'admin'; +\$user->email = 'admin@example.com'; +\$user->password = bcrypt('password'); +\$user->save(); +echo "Default admin user created: admin@example.com / password"; +TINKER + echo "==> IMPORTANT: Change the default password after first login!" +fi + +# Configure Postfix +echo "==> Configuring Postfix" +cp /tmp/postfix-main.cf /etc/postfix/main.cf +cp /tmp/postfix-master.cf /etc/postfix/master.cf + +# Update Postfix configuration with domain +sed -i "s|CLOUDRON_APP_DOMAIN|${CLOUDRON_APP_DOMAIN}|g" /etc/postfix/main.cf +sed -i "s|CLOUDRON_MAIL_DOMAIN|${CLOUDRON_MAIL_DOMAIN}|g" /etc/postfix/main.cf + +# Create Postfix directories +mkdir -p /app/data/postfix/spool +mkdir -p /var/spool/postfix +chown -R postfix:postfix /var/spool/postfix +chown -R cloudron:cloudron /app/data/postfix + +# Start services via supervisor +echo "==> Starting services" +exec /usr/bin/supervisord -c /etc/supervisor/supervisord.conf diff --git a/supervisor.conf b/supervisor.conf new file mode 100644 index 0000000..3f888df --- /dev/null +++ b/supervisor.conf @@ -0,0 +1,74 @@ +[supervisord] +nodaemon=true +user=root +logfile=/dev/null +logfile_maxbytes=0 +pidfile=/run/supervisord.pid + +[program:nginx] +command=/usr/sbin/nginx -g "daemon off;" +autostart=true +autorestart=true +priority=10 +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 + +[program:php-fpm] +command=/usr/sbin/php-fpm8.3 -F +autostart=true +autorestart=true +priority=10 +user=cloudron +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 + +[program:laravel-queue] +command=/usr/bin/php /app/code/artisan queue:work redis --sleep=3 --tries=3 --timeout=90 +directory=/app/code +autostart=true +autorestart=true +priority=20 +user=cloudron +numprocs=1 +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 +stopwaitsecs=3600 + +[program:laravel-scheduler] +command=/bin/bash -c "while true; do /usr/bin/php /app/code/artisan schedule:run --verbose --no-interaction; sleep 60; done" +directory=/app/code +autostart=true +autorestart=true +priority=20 +user=cloudron +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 + +[program:postfix] +command=/usr/sbin/postfix start-fg +autostart=true +autorestart=true +priority=15 +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 + +[program:rspamd] +command=/usr/bin/rspamd -f -u cloudron -g cloudron +autostart=true +autorestart=true +priority=15 +user=cloudron +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0