Compare commits

...

14 Commits

Author SHA1 Message Date
3cc1050007 Added License 2025-07-11 16:01:55 +00:00
e9a4d618d5 Delete .DS_Store 2025-07-06 23:33:10 +00:00
07f2ddd86d Delete BUILD.md 2025-07-06 23:33:04 +00:00
75b0d8389b Update BUILD.md 2025-07-06 23:32:45 +00:00
Andreas Dueren
74dd21b953 Initial commit of Keila Cloudron package 2025-07-06 17:01:09 -06:00
Andreas Dueren
1f81b1a775 Copy complete /usr/local and fix all Erlang paths 2025-06-20 18:25:21 -06:00
Andreas Dueren
89b9cefb8c Fix Erlang runtime paths with proper symlinks 2025-06-20 12:27:23 -06:00
Andreas Dueren
3f0a5450f4 Copy Erlang binaries to expected erts directory 2025-06-20 12:21:35 -06:00
Andreas Dueren
0e2b274fff Add Erlang runtime symlink fix for Keila release 2025-06-20 10:41:06 -06:00
Andreas Dueren
30edc87eac Copy complete Erlang runtime from Alpine image 2025-06-20 10:33:08 -06:00
Andreas Dueren
9c2ef507c0 Implement proper Cloudron structure with supervisor 2025-06-20 10:25:43 -06:00
Andreas Dueren
90e7f6b2e9 Simplify Dockerfile to use pentacent/keila base directly 2025-06-20 10:22:29 -06:00
Andreas Dueren
197d10ae2b Add Erlang runtime dependencies for Keila 2025-06-20 10:16:42 -06:00
Andreas Dueren
273aff206c Add custom nginx.conf to fix log file issues 2025-06-20 10:13:25 -06:00
9 changed files with 100 additions and 375 deletions

View File

@@ -1,9 +0,0 @@
[0.1.0]
* Initial Cloudron package for Keila v0.14.7
* PostgreSQL database integration
* SMTP configuration via Cloudron mail addon
* Persistent data storage in /app/data
* Nginx reverse proxy configuration
* Automatic secret key generation
* Default admin user creation
* Security hardening with disabled registration

View File

@@ -1,29 +1,20 @@
{
"id": "io.keila.cloudronapp",
"manifestVersion": 2,
"id": "io.keila.cloudron",
"version": "0.15.13",
"title": "Keila",
"author": "Pentacent",
"description": "Open-source newsletter tool for creating and sending email campaigns. An alternative to Mailchimp and Sendinblue.",
"tagline": "Self-hosted newsletter and email marketing platform",
"version": "0.14.7",
"healthCheckPath": "/",
"httpPort": 4000,
"manifestVersion": 2,
"website": "https://www.keila.io",
"contactEmail": "hello@keila.io",
"tags": [
"email",
"newsletter",
"marketing",
"campaigns"
],
"description": "Open-source email newsletters for creators and businesses. Keila is a reliable, self-hosted, and easy-to-use email marketing platform.",
"website": "https://www.keila.io/",
"contactEmail": "support@keila.io",
"memoryLimit": 536870912,
"httpPort": 4000,
"addons": {
"postgresql": {},
"sendmail": {},
"localstorage": {}
"localstorage": {},
"sendmail": {}
},
"healthCheckPath": "/login",
"minBoxVersion": "7.0.0",
"postInstallMessage": "file://POSTINSTALL.md",
"changelog": "file://CHANGELOG",
"optionalSso": false
}
"postInstallMessage": "Your Keila instance is ready.\n\nLogin with the following credentials:\nUsername: admin@cloudron.local\nPassword: changeme123"
}

View File

@@ -1,31 +1,38 @@
FROM cloudron/base:4.2.0
# Stage 1: Build
FROM elixir:1.15-slim AS build
# Use Keila's prebuilt image as base for the release
FROM pentacent/keila:0.14 as keila-build
# Install build dependencies
RUN apt-get update && apt-get install -y --no-install-recommends git npm build-essential cmake
FROM cloudron/base:4.2.0
# Clone Keila repository
RUN git clone --depth 1 --branch v0.15.0 https://github.com/pentacent/keila.git /keila
WORKDIR /keila
# Install runtime dependencies
RUN apt-get update \
&& apt-get install -y postgresql-client \
&& rm -rf /var/lib/apt/lists/*
# Install Elixir and NPM dependencies
ENV MIX_ENV=prod
RUN mix local.hex --force && \
mix local.rebar --force && \
mix deps.get --only prod && \
mix deps.compile
RUN npm ci --prefix ./assets
# Build the release
ENV RELEASE_INCLUDE_ERTS=true
RUN echo 'config :tzdata, autoupdate: :disabled' >> /keila/config/config.exs
RUN mix assets.deploy && \
mix release
# Stage 2: Runtime
FROM cloudron/base:5.0.0
# Create directories
RUN mkdir -p /app/code /app/data
# Copy Keila from build stage
COPY --from=keila-build /opt/app /tmp/keila-release
COPY --from=build /keila/_build/prod/rel/keila /app/code
COPY start.sh /app/code/
RUN chmod +x /app/code/start.sh
# Copy configuration files
COPY start.sh /app/code/start.sh
COPY nginx.conf /etc/nginx/sites-available/default
RUN chown -R cloudron:cloudron /app/code /app/data
# Set permissions
RUN chmod +x /app/code/start.sh \
&& chown -R cloudron:cloudron /app/code /app/data /tmp/keila-release
CMD ["/app/code/start.sh"]
WORKDIR /app/code
EXPOSE 4000
CMD ["/app/code/start.sh"]

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2025 Andreas Dueren
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 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,28 +0,0 @@
# Keila Installation Complete
Keila has been successfully installed on your Cloudron!
## Default Administrator Account
- **Email**: admin@your-domain.com
- **Password**: Check `/app/data/root_credentials` file or the application logs for the generated password
## Getting Started
1. Log in using the administrator credentials above
2. Create your first newsletter campaign
3. Set up your email sending configuration (if not using Cloudron's built-in SMTP)
4. Create sign-up forms for your newsletters
## Important Notes
- User registration is disabled by default for security
- All data is stored in `/app/data` and will persist across updates
- Email sending is configured to use Cloudron's SMTP service
- File uploads are stored in `/app/data/uploads`
## Support
- Documentation: https://www.keila.io/docs
- GitHub: https://github.com/pentacent/keila
- Issues: Please report Cloudron-specific issues to the package maintainer

143
README.md
View File

@@ -1,143 +0,0 @@
# Keila Cloudron Package
This is a Cloudron package for [Keila](https://www.keila.io), an open-source newsletter tool and alternative to Mailchimp and Sendinblue.
## Features
- **Newsletter Campaigns**: Create and send email campaigns
- **Sign-up Forms**: Generate customizable subscription forms
- **Multiple Email Providers**: Support for AWS SES, Sendgrid, Mailgun, Postmark, and SMTP
- **Self-hosted**: Complete control over your data and newsletters
- **PostgreSQL Integration**: Reliable database storage via Cloudron addon
- **SMTP Configuration**: Automatic email sending via Cloudron's mail service
## Installation
### Prerequisites
- Cloudron instance with CLI installed
- Access to build service or local Docker environment
### Build and Install
1. **Build the package**:
```bash
cloudron build --set-build-service builder.docker.due.ren \
--build-service-token e3265de06b1d0e7bb38400539012a8433a74c2c96a17955e \
--set-repository andreasdueren/keila-cloudron \
--tag 0.1.0
```
2. **Install on Cloudron**:
```bash
cloudron install --location keila.yourdomain.com \
--image andreasdueren/keila-cloudron:0.1.0
```
### Local Development Build
```bash
# Clone this repository
git clone <repository-url>
cd keila-cloudron
# Build locally
cloudron build
# Install for testing
cloudron install --location keila.local.dev
```
## Configuration
### Default Settings
- **Admin Account**: `admin@yourdomain.com` (password in `/app/data/root_credentials`)
- **Database**: PostgreSQL via Cloudron addon
- **Email**: Configured via Cloudron SMTP service
- **Registration**: Disabled by default for security
- **Port**: 4000 (proxied via nginx)
### Environment Variables
The following Cloudron environment variables are automatically configured:
- `CLOUDRON_POSTGRESQL_URL` - Database connection
- `CLOUDRON_MAIL_SMTP_*` - Email configuration
- `CLOUDRON_APP_DOMAIN` - Application domain
- `CLOUDRON_MAIL_FROM` - From email address
## Data Persistence
- **Application Data**: `/app/data/keila` - Keila installation
- **Uploads**: `/app/data/uploads` - User-uploaded content
- **Credentials**: `/app/data/root_credentials` - Admin login info
- **Secrets**: `/app/data/secret_key_base` - Application secret
## Troubleshooting
### Common Issues
1. **Database Connection**: Ensure PostgreSQL addon is properly configured
2. **Email Sending**: Verify Cloudron SMTP settings in mail addon
3. **File Permissions**: All files should be owned by `cloudron:cloudron`
### Logs
View application logs:
```bash
cloudron logs
```
### Reset Admin Password
```bash
# Access the container
cloudron exec
# Check current credentials
cat /app/data/root_credentials
# Reset if needed (restart required)
rm /app/data/root_credentials
exit
cloudron restart
```
## Technical Details
### Architecture
- **Base Image**: `cloudron/base:4.2.0`
- **Runtime**: Elixir 1.15 with Phoenix framework
- **Database**: PostgreSQL (via Cloudron addon)
- **Web Server**: Nginx reverse proxy
- **Process Manager**: Direct Elixir application startup
### Security Features
- User registration disabled by default
- Security headers configured in nginx
- File upload restrictions
- Database connection over SSL
- Secret key auto-generation
### File Structure
```
/app/code/ # Application code (read-only)
/app/data/keila/ # Keila installation
/app/data/uploads/ # User uploads
/app/data/ # Persistent data
```
## Support
- **Keila Documentation**: https://www.keila.io/docs
- **Keila GitHub**: https://github.com/pentacent/keila
- **Cloudron Docs**: https://docs.cloudron.io
## License
- **Keila**: AGPLv3 License
- **This Package**: MIT License

View File

@@ -1,84 +0,0 @@
server {
listen 4000 default_server;
listen [::]:4000 default_server;
server_name _;
root /tmp;
client_max_body_size 100m;
client_body_temp_path /tmp/nginx/body;
fastcgi_temp_path /tmp/nginx/fastcgi;
proxy_temp_path /tmp/nginx/proxy;
scgi_temp_path /tmp/nginx/scgi;
uwsgi_temp_path /tmp/nginx/uwsgi;
# Security headers
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header Referrer-Policy strict-origin-when-cross-origin;
# Logging
access_log /dev/stdout;
error_log /dev/stderr;
# Gzip compression
gzip on;
gzip_vary on;
gzip_min_length 1024;
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/atom+xml
image/svg+xml;
# Proxy to Keila application
location / {
proxy_pass http://127.0.0.1:4001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
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 $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
proxy_cache_bypass $http_upgrade;
proxy_redirect off;
# Timeout settings
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
# Health check endpoint
location /healthz {
proxy_pass http://127.0.0.1:4001/healthz;
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 $scheme;
access_log off;
}
# Static files caching
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
proxy_pass http://127.0.0.1:4001;
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 $scheme;
expires 1y;
add_header Cache-Control "public, immutable";
}
}

View File

@@ -1,5 +0,0 @@
User-agent: *
Disallow: /admin/
Disallow: /api/
Disallow: /auth/
Allow: /

101
start.sh
View File

@@ -1,73 +1,48 @@
#!/bin/bash
set -eu
echo "Starting Keila on Cloudron"
set -euo pipefail
# Copy Keila release to /app/data on first run
if [[ ! -d "/app/data/keila" ]]; then
echo "==> Initializing Keila installation"
cp -r /tmp/keila-release /app/data/keila
chown -R cloudron:cloudron /app/data/keila
fi
# Generate secret key base if not exists
if [[ ! -f "/app/data/secret_key_base" ]]; then
echo "==> Generating secret key base"
openssl rand -hex 64 > /app/data/secret_key_base
chown cloudron:cloudron /app/data/secret_key_base
fi
# Set environment variables
export SECRET_KEY_BASE=$(cat /app/data/secret_key_base)
export DB_URL="${CLOUDRON_POSTGRESQL_URL}"
export URL_HOST="${CLOUDRON_APP_DOMAIN}"
export URL_SCHEMA="https"
export URL_PORT="443"
export PORT="4000"
# Configure SMTP
export MAILER_SMTP_HOST="${CLOUDRON_MAIL_SMTP_SERVER}"
export MAILER_SMTP_PORT="${CLOUDRON_MAIL_SMTP_PORT}"
export MAILER_SMTP_USERNAME="${CLOUDRON_MAIL_SMTP_USERNAME}"
export MAILER_SMTP_PASSWORD="${CLOUDRON_MAIL_SMTP_PASSWORD}"
export MAILER_SMTP_FROM_EMAIL="${CLOUDRON_MAIL_FROM}"
# Set user content directory
export USER_CONTENT_DIR="/app/data/uploads"
# Create user content directory
mkdir -p /app/data/uploads
chown cloudron:cloudron /app/data/uploads
chown -R cloudron:cloudron /app/data
# Disable registration for security (admin can create users)
export DISABLE_REGISTRATION="true"
# Set database pool size
export DATABASE_POOL_SIZE="10"
# Create root user credentials file if not exists
if [[ ! -f "/app/data/root_credentials" ]]; then
echo "==> Generating root user credentials"
ROOT_PASSWORD=$(openssl rand -base64 32)
echo "Email: admin@${CLOUDRON_APP_DOMAIN}" > /app/data/root_credentials
echo "Password: ${ROOT_PASSWORD}" >> /app/data/root_credentials
export ROOT_EMAIL="admin@${CLOUDRON_APP_DOMAIN}"
export ROOT_PASSWORD="${ROOT_PASSWORD}"
chown cloudron:cloudron /app/data/root_credentials
chmod 600 /app/data/root_credentials
# Generate secret key on first run
if [ ! -f /app/data/secret_key.txt ]; then
echo "=> Generating new secret key"
head -c 48 /dev/urandom | base64 > /app/data/secret_key.txt
fi
echo "==> Creating nginx temp directories"
mkdir -p /tmp/nginx/body /tmp/nginx/fastcgi /tmp/nginx/proxy /tmp/nginx/scgi /tmp/nginx/uwsgi
# Export environment variables for Keila
export PORT=4000
export DB_URL=$CLOUDRON_POSTGRESQL_URL
export SECRET_KEY_BASE=$(cat /app/data/secret_key.txt)
echo "==> Starting nginx"
nginx -t
nginx
# Configure URLs from Cloudron environment variables
export URL_HOST=$CLOUDRON_APP_DOMAIN
export URL_PATH="/"
if [[ "$CLOUDRON_APP_ORIGIN" == https://* ]]; then
export URL_SCHEMA="https"
export URL_PORT="443"
else
export URL_SCHEMA="http"
export URL_PORT="80"
fi
echo "==> Running database migrations"
cd /app/data/keila
sudo -u cloudron -E /app/data/keila/bin/keila eval "Keila.Release.migrate()"
# Configure email settings
export MAILER_TYPE=smtp
export MAILER_SMTP_FROM_EMAIL=$CLOUDRON_MAIL_FROM
export MAILER_SMTP_HOST=$CLOUDRON_MAIL_SMTP_SERVER
export MAILER_SMTP_PORT=$CLOUDRON_MAIL_SMTP_PORT
export MAILER_SMTP_USER=$CLOUDRON_MAIL_SMTP_USERNAME
export MAILER_SMTP_PASSWORD=$CLOUDRON_MAIL_SMTP_PASSWORD
export MAILER_ENABLE_STARTTLS=true
echo "==> Starting Keila application"
cd /app/data/keila
# Change the internal port since nginx listens on 4000
export PORT="4001"
exec sudo -u cloudron -E /app/data/keila/bin/keila start
# Configure user content directory
export USER_CONTENT_DIR=/app/data/uploads
# Set the initial admin user
export KEILA_USER="admin@cloudron.local"
export KEILA_PASSWORD="changeme123"
echo "=> Starting Keila"
exec gosu cloudron:cloudron /app/code/bin/keila start