Compare commits

...

10 Commits

Author SHA1 Message Date
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
10 changed files with 133 additions and 375 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

54
BUILD.md Normal file
View File

@@ -0,0 +1,54 @@
# Keila on Cloudron
This document provides instructions on how to build and install the Keila package for Cloudron.
## Prerequisites
- A Cloudron instance
- Cloudron CLI installed and configured
- Docker installed locally
## Building the Package
The Keila Cloudron package is built using the `cloudron build` command. This command will use the `Dockerfile` to create a Docker image and push it to a Docker registry.
To build the package, run the following command in the root of this repository:
```bash
cloudron build --set-build-service builder.docker.due.ren --build-service-token e3265de06b1d0e7bb38400539012a8433a74c2c96a17955e --set-repository andreasdueren/keila-cloudron --tag 0.15.0
```
Replace `andreasdueren/keila-cloudron` with your own Docker Hub repository if you wish. The version `0.15.0` corresponds to the Keila version being packaged.
## Installing the Application
Once the build is complete, you can install the application on your Cloudron instance using the `cloudron install` command.
```bash
cloudron install --location keila.due.ren --image andreasdueren/keila-cloudron:0.15.0
```
Replace `keila.due.ren` with the desired location for your Keila instance.
## First-time Setup
After installation, Keila will be configured with the following settings:
- The root user is created with your Cloudron account's email address.
- To set your password for the first time, use the "Forgot Password?" link on the login page.
- Email sending is configured to use Cloudron's mail server.
- User-uploaded content is stored in `/app/data/uploads`.
## Troubleshooting
You can view the application logs from the Cloudron dashboard or using the Cloudron CLI:
```bash
cloudron logs --app keila.due.ren
```
To get a shell inside the running application container:
```bash
cloudron exec --app keila.due.ren
```

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
# Set permissions
RUN chmod +x /app/code/start.sh \
&& chown -R cloudron:cloudron /app/code /app/data /tmp/keila-release
WORKDIR /app/code
EXPOSE 4000
RUN chown -R cloudron:cloudron /app/code /app/data
CMD ["/app/code/start.sh"]

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: /

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
# Create user content directory
mkdir -p /app/data/uploads
chown -R cloudron:cloudron /app/data
# 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
# 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
# Export environment variables for Keila
export PORT=4000
export DB_URL=$CLOUDRON_POSTGRESQL_URL
export SECRET_KEY_BASE=$(cat /app/data/secret_key.txt)
# 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}"
# 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"
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"
mkdir -p /app/data/uploads
chown cloudron:cloudron /app/data/uploads
# 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
else
export URL_SCHEMA="http"
export URL_PORT="80"
fi
echo "==> Creating nginx temp directories"
mkdir -p /tmp/nginx/body /tmp/nginx/fastcgi /tmp/nginx/proxy /tmp/nginx/scgi /tmp/nginx/uwsgi
# 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 nginx"
nginx -t
nginx
# Configure user content directory
export USER_CONTENT_DIR=/app/data/uploads
echo "==> Running database migrations"
cd /app/data/keila
sudo -u cloudron -E /app/data/keila/bin/keila eval "Keila.Release.migrate()"
# Set the initial admin user
export KEILA_USER="admin@cloudron.local"
export KEILA_PASSWORD="changeme123"
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
echo "=> Starting Keila"
exec gosu cloudron:cloudron /app/code/bin/keila start