first cut of review board packaging
This commit is contained in:
44
Techops/reviewboard.knownelement.com/Dockerfile
Normal file
44
Techops/reviewboard.knownelement.com/Dockerfile
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
FROM cloudron/base:4.2.0
|
||||||
|
|
||||||
|
# Install required packages
|
||||||
|
RUN apt-get update && \
|
||||||
|
DEBIAN_FRONTEND=noninteractive apt-get install -y \
|
||||||
|
python3 python3-pip python3-dev python3-venv \
|
||||||
|
nginx supervisor \
|
||||||
|
memcached libpq-dev \
|
||||||
|
libldap2-dev libsasl2-dev \
|
||||||
|
git-core subversion \
|
||||||
|
libxml2-dev libxslt1-dev \
|
||||||
|
libmagic-dev \
|
||||||
|
gcc && \
|
||||||
|
apt-get clean && \
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Create Python virtual environment
|
||||||
|
RUN python3 -m venv /app/code/venv
|
||||||
|
ENV PATH="/app/code/venv/bin:${PATH}"
|
||||||
|
|
||||||
|
# Install Review Board dependencies
|
||||||
|
RUN pip3 install --no-cache-dir --upgrade pip wheel setuptools && \
|
||||||
|
pip3 install --no-cache-dir psycopg2-binary gunicorn django-storages
|
||||||
|
|
||||||
|
# Install Review Board
|
||||||
|
RUN pip3 install --no-cache-dir reviewboard
|
||||||
|
|
||||||
|
# Install OIDC authentication
|
||||||
|
RUN pip3 install --no-cache-dir mozilla-django-oidc
|
||||||
|
|
||||||
|
# Install LDAP authentication
|
||||||
|
RUN pip3 install --no-cache-dir django-auth-ldap
|
||||||
|
|
||||||
|
# Make the data directories ready
|
||||||
|
RUN mkdir -p /app/data/media /app/data/static /app/data/logs /app/data/conf /app/data/site
|
||||||
|
|
||||||
|
# Copy configuration files
|
||||||
|
COPY nginx.conf /etc/nginx/sites-available/default
|
||||||
|
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
|
||||||
|
COPY start.sh /app/code/start.sh
|
||||||
|
RUN chmod +x /app/code/start.sh
|
||||||
|
|
||||||
|
# Set up the entry point
|
||||||
|
CMD ["/app/code/start.sh"]
|
147
Techops/reviewboard.knownelement.com/ReviewBoard-BuildNotes.md
Normal file
147
Techops/reviewboard.knownelement.com/ReviewBoard-BuildNotes.md
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
# Review Board - Cloudron Build Notes
|
||||||
|
|
||||||
|
This document provides instructions for building, testing, and deploying the Review Board Cloudron package.
|
||||||
|
|
||||||
|
## Package Overview
|
||||||
|
|
||||||
|
Review Board is a powerful web-based code review tool that helps teams review code, documents, and images before they are committed. This package configures Review Board to run on Cloudron with the following features:
|
||||||
|
|
||||||
|
- PostgreSQL database for data storage
|
||||||
|
- Memcached for caching
|
||||||
|
- Nginx as the web server
|
||||||
|
- Gunicorn as the WSGI server
|
||||||
|
- Support for Cloudron’s OIDC and LDAP authentication
|
||||||
|
- Proper data separation following Cloudron’s filesystem layout
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
1. Cloudron CLI tool installed (`npm install -g cloudron`)
|
||||||
|
2. Docker installed and running
|
||||||
|
3. Cloudron account with administrative access
|
||||||
|
|
||||||
|
## Files Included in the Package
|
||||||
|
|
||||||
|
1. **CloudronManifest.json** - Defines the application for Cloudron
|
||||||
|
2. **Dockerfile** - Instructions for building the Docker image
|
||||||
|
3. **start.sh** - Initialization and startup script
|
||||||
|
4. **supervisord.conf** - Process management configuration
|
||||||
|
5. **nginx.conf** - Web server configuration
|
||||||
|
|
||||||
|
## Building the Package
|
||||||
|
|
||||||
|
1. Create a new directory for your package files:
|
||||||
|
```bash
|
||||||
|
mkdir reviewboard-cloudron
|
||||||
|
cd reviewboard-cloudron
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Create all the package files in this directory.
|
||||||
|
|
||||||
|
3. Download the Review Board icon and save it as `icon.png`:
|
||||||
|
```bash
|
||||||
|
curl -L “https://raw.githubusercontent.com/reviewboard/reviewboard/master/reviewboard/static/rb/images/logo.png” -o icon.png
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Build the package:
|
||||||
|
```bash
|
||||||
|
cloudron build
|
||||||
|
```
|
||||||
|
|
||||||
|
## Testing Locally (Optional)
|
||||||
|
|
||||||
|
1. Run the Docker image locally to test basic functionality:
|
||||||
|
```bash
|
||||||
|
docker run -p 8000:8000 cloudron/reviewboard-app:1.0.0
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Access the application at http://localhost:8000 to check if it starts correctly.
|
||||||
|
|
||||||
|
## Deploying to Cloudron
|
||||||
|
|
||||||
|
1. Install the package on your Cloudron:
|
||||||
|
```bash
|
||||||
|
cloudron install —image cloudron/reviewboard-app:1.0.0
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Or, to update an existing installation:
|
||||||
|
```bash
|
||||||
|
cloudron update —image cloudron/reviewboard-app:1.0.0 —app reviewboard.yourdomain.com
|
||||||
|
```
|
||||||
|
|
||||||
|
## Post-Installation
|
||||||
|
|
||||||
|
1. Access your Review Board instance at the URL assigned by Cloudron.
|
||||||
|
2. Log in using the initial admin credentials:
|
||||||
|
- Username: `admin`
|
||||||
|
- Password: Check the file `/app/data/admin_password.txt` inside the app container:
|
||||||
|
```bash
|
||||||
|
cloudron exec —app reviewboard.yourdomain.com cat /app/data/admin_password.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Configure your repository connections in the Review Board admin interface at `/admin/`.
|
||||||
|
|
||||||
|
## Authentication Details
|
||||||
|
|
||||||
|
### OIDC Authentication (Default)
|
||||||
|
|
||||||
|
The package is configured to use Cloudron’s OIDC provider when available. Users logging in via OIDC will be automatically provisioned in Review Board.
|
||||||
|
|
||||||
|
### LDAP Authentication (Alternative)
|
||||||
|
|
||||||
|
If OIDC is not available, the package will fall back to using Cloudron’s LDAP server for authentication.
|
||||||
|
|
||||||
|
## Repository Support
|
||||||
|
|
||||||
|
Review Board supports the following repository types:
|
||||||
|
- Git
|
||||||
|
- SVN
|
||||||
|
- Mercurial
|
||||||
|
- Perforce
|
||||||
|
- Bazaar
|
||||||
|
- CVS
|
||||||
|
- IBM Rational ClearCase
|
||||||
|
- And more
|
||||||
|
|
||||||
|
Configure these in the Admin > Repositories section after login.
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
1. Check application logs:
|
||||||
|
```bash
|
||||||
|
cloudron logs —app reviewboard.yourdomain.com
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Access the container directly to troubleshoot:
|
||||||
|
```bash
|
||||||
|
cloudron exec —app reviewboard.yourdomain.com bash
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Validate database connectivity:
|
||||||
|
```bash
|
||||||
|
cloudron exec —app reviewboard.yourdomain.com psql “$CLOUDRON_POSTGRESQL_URL”
|
||||||
|
```
|
||||||
|
|
||||||
|
4. If Review Board shows errors about missing repositories, ensure they are accessible from the Cloudron container.
|
||||||
|
|
||||||
|
## Backup and Restore
|
||||||
|
|
||||||
|
Cloudron automatically backs up the `/app/data` directory, which includes:
|
||||||
|
- Database (via PostgreSQL addon)
|
||||||
|
- Media files (uploaded files, screenshots, etc.)
|
||||||
|
- Configuration files
|
||||||
|
- Repository cache
|
||||||
|
|
||||||
|
No additional backup configuration is necessary.
|
||||||
|
|
||||||
|
## Upgrading Review Board
|
||||||
|
|
||||||
|
When a new version of Review Board is released:
|
||||||
|
|
||||||
|
1. Update the Dockerfile to install the new version
|
||||||
|
2. Rebuild the Docker image
|
||||||
|
3. Update the Cloudron app using the `cloudron update` command
|
||||||
|
|
||||||
|
## Additional Resources
|
||||||
|
|
||||||
|
- [Review Board Documentation](https://www.reviewboard.org/docs/)
|
||||||
|
- [Cloudron Documentation](https://docs.cloudron.io/)
|
43
Techops/reviewboard.knownelement.com/nginx.conf
Normal file
43
Techops/reviewboard.knownelement.com/nginx.conf
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
server {
|
||||||
|
listen 8000;
|
||||||
|
server_name CLOUDRON_APP_DOMAIN;
|
||||||
|
|
||||||
|
client_max_body_size 100M;
|
||||||
|
|
||||||
|
# Handle static and media files
|
||||||
|
location /static/ {
|
||||||
|
alias /app/data/static/;
|
||||||
|
expires 30d;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /media/ {
|
||||||
|
alias /app/data/media/;
|
||||||
|
expires 30d;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Forward requests to the Django application
|
||||||
|
location / {
|
||||||
|
proxy_pass http://127.0.0.1:8001;
|
||||||
|
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_connect_timeout 300s;
|
||||||
|
proxy_read_timeout 300s;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Set up OIDC callback path
|
||||||
|
location /api/v1/session/callback {
|
||||||
|
proxy_pass http://127.0.0.1:8001;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Handle errors
|
||||||
|
error_page 500 502 503 504 /50x.html;
|
||||||
|
location = /50x.html {
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
}
|
||||||
|
}
|
187
Techops/reviewboard.knownelement.com/start.sh
Normal file
187
Techops/reviewboard.knownelement.com/start.sh
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Create data directories if they don't exist
|
||||||
|
if [ ! -f /app/data/.initialized ]; then
|
||||||
|
echo "Initializing Review Board data directories..."
|
||||||
|
|
||||||
|
# Create directories
|
||||||
|
mkdir -p /app/data/conf
|
||||||
|
mkdir -p /app/data/media
|
||||||
|
mkdir -p /app/data/static
|
||||||
|
mkdir -p /app/data/logs
|
||||||
|
|
||||||
|
# Generate a random admin password and save it
|
||||||
|
ADMIN_PASSWORD=$(< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c16)
|
||||||
|
echo $ADMIN_PASSWORD > /app/data/admin_password.txt
|
||||||
|
chmod 640 /app/data/admin_password.txt
|
||||||
|
|
||||||
|
# Mark as initialized
|
||||||
|
touch /app/data/.initialized
|
||||||
|
echo "Initialization complete."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Set proper ownership
|
||||||
|
chown -R cloudron:cloudron /app/data
|
||||||
|
|
||||||
|
# Configure database connection
|
||||||
|
if [ ! -f /app/data/conf/settings_local.py ]; then
|
||||||
|
echo "Creating Review Board configuration..."
|
||||||
|
|
||||||
|
# Get database connection details from CLOUDRON_POSTGRESQL_URL
|
||||||
|
DB_HOST=$(echo "${CLOUDRON_POSTGRESQL_URL}" | cut -d@ -f2 | cut -d/ -f1)
|
||||||
|
DB_NAME=$(echo "${CLOUDRON_POSTGRESQL_URL}" | cut -d/ -f4)
|
||||||
|
DB_USER=$(echo "${CLOUDRON_POSTGRESQL_URL}" | cut -d/ -f3 | cut -d: -f1)
|
||||||
|
DB_PASSWORD=$(echo "${CLOUDRON_POSTGRESQL_URL}" | cut -d: -f3 | cut -d@ -f1)
|
||||||
|
|
||||||
|
# Create settings_local.py
|
||||||
|
cat > /app/data/conf/settings_local.py << EOF
|
||||||
|
# Cloudron Review Board Settings
|
||||||
|
import os
|
||||||
|
|
||||||
|
# Database settings
|
||||||
|
DATABASES = {
|
||||||
|
'default': {
|
||||||
|
'ENGINE': 'django.db.backends.postgresql',
|
||||||
|
'NAME': '${DB_NAME}',
|
||||||
|
'USER': '${DB_USER}',
|
||||||
|
'PASSWORD': '${DB_PASSWORD}',
|
||||||
|
'HOST': '${DB_HOST}',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Site settings
|
||||||
|
SITE_ROOT = '/'
|
||||||
|
MEDIA_ROOT = '/app/data/media'
|
||||||
|
STATIC_ROOT = '/app/data/static'
|
||||||
|
|
||||||
|
# Email settings
|
||||||
|
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
|
||||||
|
EMAIL_HOST = 'mail'
|
||||||
|
EMAIL_PORT = 25
|
||||||
|
DEFAULT_FROM_EMAIL = 'reviewboard@${CLOUDRON_APP_DOMAIN}'
|
||||||
|
SERVER_EMAIL = 'reviewboard@${CLOUDRON_APP_DOMAIN}'
|
||||||
|
|
||||||
|
# Cache settings
|
||||||
|
CACHES = {
|
||||||
|
'default': {
|
||||||
|
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
|
||||||
|
'LOCATION': '127.0.0.1:11211',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Add authentication settings based on Cloudron's environment
|
||||||
|
if [ -n "${CLOUDRON_LDAP_SERVER}" ]; then
|
||||||
|
# LDAP Authentication
|
||||||
|
cat >> /app/data/conf/settings_local.py << EOF
|
||||||
|
# LDAP Authentication
|
||||||
|
AUTHENTICATION_BACKENDS = (
|
||||||
|
'django_auth_ldap.backend.LDAPBackend',
|
||||||
|
'django.contrib.auth.backends.ModelBackend',
|
||||||
|
)
|
||||||
|
|
||||||
|
import ldap
|
||||||
|
from django_auth_ldap.config import LDAPSearch, GroupOfNamesType
|
||||||
|
|
||||||
|
AUTH_LDAP_SERVER_URI = "ldap://${CLOUDRON_LDAP_SERVER}:${CLOUDRON_LDAP_PORT}"
|
||||||
|
AUTH_LDAP_BIND_DN = "${CLOUDRON_LDAP_BIND_DN}"
|
||||||
|
AUTH_LDAP_BIND_PASSWORD = "${CLOUDRON_LDAP_BIND_PASSWORD}"
|
||||||
|
AUTH_LDAP_USER_SEARCH = LDAPSearch(
|
||||||
|
"${CLOUDRON_LDAP_USERS_BASE_DN}",
|
||||||
|
ldap.SCOPE_SUBTREE,
|
||||||
|
"(${CLOUDRON_LDAP_USERNAME_FIELD}=%(user)s)"
|
||||||
|
)
|
||||||
|
AUTH_LDAP_GROUP_SEARCH = LDAPSearch(
|
||||||
|
"${CLOUDRON_LDAP_GROUPS_BASE_DN}",
|
||||||
|
ldap.SCOPE_SUBTREE,
|
||||||
|
"(objectClass=groupOfNames)"
|
||||||
|
)
|
||||||
|
AUTH_LDAP_GROUP_TYPE = GroupOfNamesType()
|
||||||
|
AUTH_LDAP_USER_ATTR_MAP = {
|
||||||
|
"first_name": "givenName",
|
||||||
|
"last_name": "sn",
|
||||||
|
"email": "mail"
|
||||||
|
}
|
||||||
|
AUTH_LDAP_ALWAYS_UPDATE_USER = True
|
||||||
|
EOF
|
||||||
|
elif [ -n "${CLOUDRON_OIDC_IDENTIFIER}" ]; then
|
||||||
|
# OIDC Authentication
|
||||||
|
cat >> /app/data/conf/settings_local.py << EOF
|
||||||
|
# OIDC Authentication
|
||||||
|
AUTHENTICATION_BACKENDS = (
|
||||||
|
'mozilla_django_oidc.auth.OIDCAuthenticationBackend',
|
||||||
|
'django.contrib.auth.backends.ModelBackend',
|
||||||
|
)
|
||||||
|
|
||||||
|
OIDC_RP_CLIENT_ID = "${CLOUDRON_OIDC_CLIENT_ID}"
|
||||||
|
OIDC_RP_CLIENT_SECRET = "${CLOUDRON_OIDC_CLIENT_SECRET}"
|
||||||
|
OIDC_OP_AUTHORIZATION_ENDPOINT = "${CLOUDRON_OIDC_ENDPOINT}/authorize"
|
||||||
|
OIDC_OP_TOKEN_ENDPOINT = "${CLOUDRON_OIDC_ENDPOINT}/token"
|
||||||
|
OIDC_OP_USER_ENDPOINT = "${CLOUDRON_OIDC_ENDPOINT}/userinfo"
|
||||||
|
OIDC_OP_JWKS_ENDPOINT = "${CLOUDRON_OIDC_ENDPOINT}/jwks"
|
||||||
|
OIDC_AUTHENTICATE_CLASS = 'mozilla_django_oidc.views.OIDCAuthenticationRequestView'
|
||||||
|
OIDC_CALLBACK_CLASS = 'mozilla_django_oidc.views.OIDCAuthenticationCallbackView'
|
||||||
|
LOGIN_REDIRECT_URL = '/'
|
||||||
|
LOGOUT_REDIRECT_URL = '/'
|
||||||
|
|
||||||
|
def oidc_username_transform(username):
|
||||||
|
return username.split('@')[0]
|
||||||
|
|
||||||
|
OIDC_USERNAME_ALGO = oidc_username_transform
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Initialize the Review Board site if not already done
|
||||||
|
if [ ! -f /app/data/.db_initialized ]; then
|
||||||
|
echo "Setting up the Review Board site..."
|
||||||
|
|
||||||
|
# Get database connection details
|
||||||
|
DB_HOST=$(echo "${CLOUDRON_POSTGRESQL_URL}" | cut -d@ -f2 | cut -d/ -f1)
|
||||||
|
DB_NAME=$(echo "${CLOUDRON_POSTGRESQL_URL}" | cut -d/ -f4)
|
||||||
|
DB_USER=$(echo "${CLOUDRON_POSTGRESQL_URL}" | cut -d/ -f3 | cut -d: -f1)
|
||||||
|
DB_PASSWORD=$(echo "${CLOUDRON_POSTGRESQL_URL}" | cut -d: -f3 | cut -d@ -f1)
|
||||||
|
|
||||||
|
# Create a site directory for Review Board
|
||||||
|
rb-site install --noinput \
|
||||||
|
--domain-name=${CLOUDRON_APP_DOMAIN} \
|
||||||
|
--site-root=/ \
|
||||||
|
--static-url=static/ \
|
||||||
|
--media-url=media/ \
|
||||||
|
--db-type=postgresql \
|
||||||
|
--db-name=${DB_NAME} \
|
||||||
|
--db-user=${DB_USER} \
|
||||||
|
--db-pass=${DB_PASSWORD} \
|
||||||
|
--db-host=${DB_HOST} \
|
||||||
|
--cache-type=memcached \
|
||||||
|
--cache-info=localhost:11211 \
|
||||||
|
--web-server-type=wsgi \
|
||||||
|
--admin-user=admin \
|
||||||
|
--admin-password=$(cat /app/data/admin_password.txt) \
|
||||||
|
--admin-email=admin@${CLOUDRON_APP_DOMAIN} \
|
||||||
|
/app/data/site
|
||||||
|
|
||||||
|
# Copy settings_local.py to the site
|
||||||
|
cp /app/data/conf/settings_local.py /app/data/site/conf/settings_local.py
|
||||||
|
|
||||||
|
# Mark as initialized
|
||||||
|
touch /app/data/.db_initialized
|
||||||
|
echo "Database initialization complete."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Collect static files if they don't exist yet
|
||||||
|
if [ ! -f /app/data/.static_collected ]; then
|
||||||
|
echo "Collecting static files..."
|
||||||
|
cd /app/data/site
|
||||||
|
PYTHONPATH=/app/data/site python /app/data/site/manage.py collectstatic --noinput
|
||||||
|
touch /app/data/.static_collected
|
||||||
|
echo "Static files collected."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Configure NGINX to use the static and media directories
|
||||||
|
sed -i "s|CLOUDRON_APP_DOMAIN|${CLOUDRON_APP_DOMAIN}|g" /etc/nginx/sites-available/default
|
||||||
|
|
||||||
|
# Start services using supervisord
|
||||||
|
echo "Starting Review Board..."
|
||||||
|
exec /usr/bin/supervisord -c /etc/supervisor/supervisord.conf
|
35
Techops/reviewboard.knownelement.com/supervisord.conf
Normal file
35
Techops/reviewboard.knownelement.com/supervisord.conf
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
[supervisord]
|
||||||
|
nodaemon=true
|
||||||
|
logfile=/dev/stdout
|
||||||
|
logfile_maxbytes=0
|
||||||
|
user=root
|
||||||
|
|
||||||
|
[program:memcached]
|
||||||
|
command=/usr/bin/memcached -m 64 -p 11211 -u nobody -l 127.0.0.1
|
||||||
|
autostart=true
|
||||||
|
autorestart=true
|
||||||
|
stdout_logfile=/dev/stdout
|
||||||
|
stdout_logfile_maxbytes=0
|
||||||
|
stderr_logfile=/dev/stderr
|
||||||
|
stderr_logfile_maxbytes=0
|
||||||
|
|
||||||
|
[program:reviewboard]
|
||||||
|
command=/app/code/venv/bin/gunicorn --bind 127.0.0.1:8001 --workers 2 --timeout 90 wsgi:application
|
||||||
|
directory=/app/data/site
|
||||||
|
user=cloudron
|
||||||
|
autostart=true
|
||||||
|
autorestart=true
|
||||||
|
stdout_logfile=/dev/stdout
|
||||||
|
stdout_logfile_maxbytes=0
|
||||||
|
stderr_logfile=/dev/stderr
|
||||||
|
stderr_logfile_maxbytes=0
|
||||||
|
environment=HOME="/app/data",PYTHONPATH="/app/data/site"
|
||||||
|
|
||||||
|
[program:nginx]
|
||||||
|
command=/usr/sbin/nginx -g "daemon off;"
|
||||||
|
autostart=true
|
||||||
|
autorestart=true
|
||||||
|
stdout_logfile=/dev/stdout
|
||||||
|
stdout_logfile_maxbytes=0
|
||||||
|
stderr_logfile=/dev/stderr
|
||||||
|
stderr_logfile_maxbytes=0
|
Reference in New Issue
Block a user