Updated database & Implemented Docker support. (unfinished)
This commit is contained in:
parent
c380556255
commit
85a81784f9
25 changed files with 752 additions and 105 deletions
20
.env
Normal file
20
.env
Normal file
|
@ -0,0 +1,20 @@
|
|||
# Socialbox Configuration
|
||||
LOG_LEVEL=debug
|
||||
SB_MODE=automated
|
||||
SB_DOMAIN=localhost
|
||||
SB_RPC_ENDPOINT=http://127.0.0.0:8085/
|
||||
|
||||
# MariaDB Configuration
|
||||
MYSQL_ROOT_PASSWORD=sb_root
|
||||
MYSQL_DATABASE=socialbox
|
||||
MYSQL_USER=socialbox
|
||||
MYSQL_PASSWORD=socialbox
|
||||
|
||||
# Redis Configuration
|
||||
REDIS_PASSWORD=root
|
||||
|
||||
# Test Configuration, can be ignored. Used for docker-compose-test.yml
|
||||
SB_ALICE_DOMAIN=localhost
|
||||
SB_ALICE_RPC_ENDPOINT=http://127.0.0.0:8086/
|
||||
SB_BOB_DOMAIN=localhost
|
||||
SB_BOB_RPC_ENDPOINT=http://127.0.0.0:8087/
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,3 +1,4 @@
|
|||
/build
|
||||
/.idea/gbrowser_project.xml
|
||||
.phpunit.result.cache
|
||||
/socialbox
|
2
.idea/sqldialects.xml
generated
2
.idea/sqldialects.xml
generated
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="SqlDialectMappings">
|
||||
<file url="file://$PROJECT_DIR$/src/Socialbox/Classes/Resources/database/password_authentication.sql" dialect="MariaDB" />
|
||||
<file url="file://$PROJECT_DIR$/src/Socialbox/Classes/Resources/database/captcha_images.sql" dialect="MariaDB" />
|
||||
<file url="file://$PROJECT_DIR$/src/Socialbox/Classes/Resources/database/registered_peers.sql" dialect="MariaDB" />
|
||||
<file url="file://$PROJECT_DIR$/src/Socialbox/Classes/Resources/database/sessions.sql" dialect="MariaDB" />
|
||||
<file url="file://$PROJECT_DIR$/src/Socialbox/Classes/Resources/database/variables.sql" dialect="MariaDB" />
|
||||
|
|
1
.idea/webResources.xml
generated
1
.idea/webResources.xml
generated
|
@ -7,6 +7,7 @@
|
|||
<resourceRoots>
|
||||
<path value="file://$PROJECT_DIR$/examples" />
|
||||
<path value="file://$PROJECT_DIR$/src/Socialbox/Classes/Resources" />
|
||||
<path value="file://$PROJECT_DIR$/public" />
|
||||
</resourceRoots>
|
||||
</entryData>
|
||||
</entry>
|
||||
|
|
119
Dockerfile
Normal file
119
Dockerfile
Normal file
|
@ -0,0 +1,119 @@
|
|||
# -----------------------------------------------------------------------------
|
||||
# Dockerfile for PHP 8.3 + FPM with Cron support and Supervisor
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
# Base image: Official PHP 8.3 with FPM
|
||||
FROM php:8.3-fpm AS base
|
||||
|
||||
# ----------------------------- Metadata labels ------------------------------
|
||||
LABEL maintainer="Netkas <netkas@n64.cc>" \
|
||||
version="1.0" \
|
||||
description="Socialbox Docker image based off PHP 8.3 FPM and NCC" \
|
||||
application="SocialBox" \
|
||||
base_image="php:8.3-fpm"
|
||||
|
||||
# Environment variable for non-interactive installations
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
# ----------------------------- System Dependencies --------------------------
|
||||
# Update system packages and install required dependencies in one step
|
||||
RUN apt-get update -yqq && apt-get install -yqq --no-install-recommends \
|
||||
git \
|
||||
libpq-dev \
|
||||
libzip-dev \
|
||||
zip \
|
||||
make \
|
||||
wget \
|
||||
gnupg \
|
||||
cron \
|
||||
supervisor \
|
||||
mariadb-client \
|
||||
libcurl4-openssl-dev \
|
||||
libmemcached-dev \
|
||||
redis \
|
||||
libgd-dev \
|
||||
nginx \
|
||||
&& apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# ----------------------------- PHP Extensions -------------------------------
|
||||
# Install PHP extensions and enable additional ones
|
||||
RUN docker-php-ext-install -j$(nproc) \
|
||||
pdo \
|
||||
pdo_mysql \
|
||||
mysqli \
|
||||
gd \
|
||||
curl \
|
||||
opcache \
|
||||
zip \
|
||||
pcntl && \
|
||||
pecl install redis memcached && \
|
||||
docker-php-ext-enable redis memcached
|
||||
|
||||
# ----------------------------- Additional Tools -----------------------------
|
||||
# Install Phive (Package Manager for PHAR libraries) and global tools in one step
|
||||
RUN wget -O /usr/local/bin/phive https://phar.io/releases/phive.phar && \
|
||||
wget -O /usr/local/bin/phive.asc https://phar.io/releases/phive.phar.asc && \
|
||||
gpg --keyserver hkps://keys.openpgp.org --recv-keys 0x9D8A98B29B2D5D79 && \
|
||||
gpg --verify /usr/local/bin/phive.asc /usr/local/bin/phive && \
|
||||
chmod +x /usr/local/bin/phive && \
|
||||
phive install phpab --global --trust-gpg-keys 0x2A8299CE842DD38C
|
||||
|
||||
# ----------------------------- Clone and Build NCC --------------------------
|
||||
# Clone the NCC repository, build the project, and install it
|
||||
RUN git clone https://git.n64.cc/nosial/ncc.git && \
|
||||
cd ncc && \
|
||||
make redist && \
|
||||
NCC_DIR=$(find build/ -type d -name "ncc_*" | head -n 1) && \
|
||||
if [ -z "$NCC_DIR" ]; then \
|
||||
echo "NCC build directory not found"; \
|
||||
exit 1; \
|
||||
fi && \
|
||||
php "$NCC_DIR/INSTALL" --auto && \
|
||||
cd .. && rm -rf ncc
|
||||
|
||||
# ----------------------------- Project Build ---------------------------------
|
||||
# Set build directory and copy pre-needed project files
|
||||
WORKDIR /tmp/build
|
||||
COPY . .
|
||||
|
||||
RUN ncc build --config release --build-source --log-level debug && \
|
||||
ncc package install --package=build/release/net.nosial.socialbox.ncc --build-source -y --log-level=debug
|
||||
|
||||
# Clean up
|
||||
RUN rm -rf /tmp/build && rm -rf /var/www/html/*
|
||||
|
||||
# Copy over the required files
|
||||
COPY nginx.conf /etc/nginx/nginx.conf
|
||||
COPY public/index.php /var/www/html/index.php
|
||||
RUN chown -R www-data:www-data /var/www/html && chmod -R 755 /var/www/html
|
||||
|
||||
# ----------------------------- Cron Configuration ---------------------------
|
||||
RUN echo "*/1 * * * * root for i in {1..12}; do /usr/bin/socialbox process-outgoing; sleep 5; done" > /etc/cron.d/socialbox-process-outgoing && \
|
||||
echo "*/1 * * * * root /usr/bin/socialbox session-cleanup" > /etc/cron.d/socialbox-session-cleanup && \
|
||||
echo "*/5 * * * * root /usr/bin/socialbox peer-cleanup" > /etc/cron.d/socialbox-peer-cleanup && \
|
||||
\
|
||||
chmod 0644 /etc/cron.d/socialbox-process-outgoing && \
|
||||
chmod 0644 /etc/cron.d/socialbox-session-cleanup && \
|
||||
chmod 0644 /etc/cron.d/socialbox-peer-cleanup && \
|
||||
\
|
||||
crontab /etc/cron.d/socialbox-process-outgoing && \
|
||||
crontab /etc/cron.d/socialbox-session-cleanup && \
|
||||
crontab /etc/cron.d/socialbox-peer-cleanup
|
||||
|
||||
# ----------------------------- Supervisor Configuration ---------------------
|
||||
# Copy Supervisor configuration
|
||||
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
|
||||
|
||||
# ----------------------------- Cleanup ---------------------
|
||||
WORKDIR /
|
||||
|
||||
# ----------------------------- Port Exposing ---------------------------------
|
||||
EXPOSE 8085
|
||||
|
||||
# ----------------------------- Container Startup ----------------------------
|
||||
# Copy over entrypoint script and set it as executable
|
||||
COPY entrypoint.sh /usr/local/bin/entrypoint.sh
|
||||
RUN chmod +x /usr/local/bin/entrypoint.sh
|
||||
|
||||
# Set the entrypoint
|
||||
ENTRYPOINT ["/usr/bin/bash", "/usr/local/bin/entrypoint.sh"]
|
98
docker-compose.yml
Normal file
98
docker-compose.yml
Normal file
|
@ -0,0 +1,98 @@
|
|||
services:
|
||||
socialbox:
|
||||
container_name: socialbox
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
ports:
|
||||
- "8085:8085"
|
||||
depends_on:
|
||||
mariadb:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_healthy
|
||||
networks:
|
||||
- internal_network
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ./socialbox/config:/etc/config
|
||||
- ./socialbox/logs:/var/log
|
||||
- ./socialbox/data:/etc/socialbox
|
||||
environment:
|
||||
# No need to change these values
|
||||
LOG_LEVEL: ${LOG_LEVEL:-debug}
|
||||
CONFIGLIB_PATH: /etc/config
|
||||
LOGGING_DIRECTORY: /var/log
|
||||
SB_MODE: automated
|
||||
SB_STORAGE_PATH: /etc/socialbox
|
||||
# Change these values to match your environment or update the .env file
|
||||
SB_INSTANCE_DOMAIN: ${SB_DOMAIN:-localhost}
|
||||
SB_INSTANCE_RPC_ENDPOINT: ${SB_RPC_ENDPOINT:-http://127.0.0.0:8085/}
|
||||
SB_DATABASE_HOST: mariadb
|
||||
SB_DATABASE_USERNAME: ${MYSQL_USER:-socialbox}
|
||||
SB_DATABASE_PASSWORD: ${MYSQL_PASSWORD:-socialbox}
|
||||
SB_DATABASE_NAME: ${MYSQL_DATABASE:-socialbox}
|
||||
SB_CACHE_ENGINE: redis
|
||||
SB_CACHE_HOST: redis
|
||||
SB_CACHE_PASSWORD: ${REDIS_PASSWORD:-root}
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "-H", "Request-Type: ping", "${SB_INSTANCE_DOMAIN-http://127.0.0.0:8085/}"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
|
||||
mariadb:
|
||||
container_name: socialbox_mariadb
|
||||
image: mariadb:10.5
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-sb_root}
|
||||
MYSQL_DATABASE: ${MYSQL_DATABASE:-socialbox}
|
||||
MYSQL_USER: ${MYSQL_USER:-socialbox}
|
||||
MYSQL_PASSWORD: ${MYSQL_PASSWORD:-socialbox}
|
||||
volumes:
|
||||
- mariadb_data:/var/lib/mysql
|
||||
networks:
|
||||
- internal_network
|
||||
expose:
|
||||
- "3306"
|
||||
healthcheck:
|
||||
test: ["CMD", "mysqladmin", "ping", "-h", "mariadb", "-u", "${MYSQL_USER:-socialbox}", "-p${MYSQL_PASSWORD:-socialbox}"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 30s
|
||||
|
||||
redis:
|
||||
container_name: socialbox_redis
|
||||
image: redis:alpine
|
||||
restart: unless-stopped
|
||||
command: redis-server /usr/local/etc/redis/redis.conf --appendonly yes
|
||||
volumes:
|
||||
- redis_data:/data
|
||||
- ./redis.conf:/usr/local/etc/redis/redis.conf
|
||||
networks:
|
||||
- internal_network
|
||||
environment:
|
||||
REDIS_PASSWORD: ${REDIS_PASSWORD:-root}
|
||||
REDIS_DB: 0
|
||||
expose:
|
||||
- "6379"
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 5s
|
||||
|
||||
volumes:
|
||||
mariadb_data:
|
||||
driver: local
|
||||
redis_data:
|
||||
driver: local
|
||||
|
||||
networks:
|
||||
internal_network:
|
||||
driver: bridge
|
||||
name: socialbox_network
|
23
entrypoint.sh
Normal file
23
entrypoint.sh
Normal file
|
@ -0,0 +1,23 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Banner with cool ASCII art
|
||||
echo "███████╗ ██████╗ ██████╗██╗ █████╗ ██╗ ██████╗ ██████╗ ██╗ ██╗"
|
||||
echo "██╔════╝██╔═══██╗██╔════╝██║██╔══██╗██║ ██╔══██╗██╔═══██╗╚██╗██╔╝"
|
||||
echo "███████╗██║ ██║██║ ██║███████║██║ ██████╔╝██║ ██║ ╚███╔╝ "
|
||||
echo "╚════██║██║ ██║██║ ██║██╔══██║██║ ██╔══██╗██║ ██║ ██╔██╗ "
|
||||
echo "███████║╚██████╔╝╚██████╗██║██║ ██║███████╗██████╔╝╚██████╔╝██╔╝ ██╗"
|
||||
echo "╚══════╝ ╚═════╝ ╚═════╝╚═╝╚═╝ ╚═╝╚══════╝╚═════╝ ╚═════╝ ╚═╝ ╚═╝"
|
||||
|
||||
# Check if the environment variable SB_MODE is set to "automated", if not exit.
|
||||
if [ "$SB_MODE" != "automated" ]; then
|
||||
echo "SB_MODE is not set to 'automated', exiting..."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Initialize Socialbox
|
||||
echo "Initializing Socialbox..."
|
||||
/usr/bin/socialbox init --log-level=${LOG_LEVEL-INFO}
|
||||
|
||||
# Run supervisord, final command
|
||||
echo "Starting supervisord..."
|
||||
/usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf
|
37
nginx.conf
Normal file
37
nginx.conf
Normal file
|
@ -0,0 +1,37 @@
|
|||
http {
|
||||
include mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
server {
|
||||
listen 8085;
|
||||
server_name localhost;
|
||||
|
||||
access_log /var/log/access.log;
|
||||
error_log /var/log/error.log;
|
||||
|
||||
root /var/www/html;
|
||||
index index.php;
|
||||
|
||||
# Handle all requests
|
||||
location / {
|
||||
try_files $uri $uri/ /index.php?$query_string =503;
|
||||
autoindex off;
|
||||
}
|
||||
|
||||
location ~ \.php$ {
|
||||
include fastcgi_params;
|
||||
fastcgi_pass 127.0.0.1:9000;
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
}
|
||||
|
||||
# Block any .ht* files
|
||||
location ~ /\.ht {
|
||||
deny all;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
|
@ -93,7 +93,7 @@
|
|||
"execute": {
|
||||
"working_directory": "%CWD%",
|
||||
"silent": false,
|
||||
"tty": true,
|
||||
"tty": false,
|
||||
"timeout": null,
|
||||
"idle_timeout": null,
|
||||
"target": "main"
|
||||
|
|
4
redis.conf
Normal file
4
redis.conf
Normal file
|
@ -0,0 +1,4 @@
|
|||
bind 0.0.0.0
|
||||
protected-mode yes
|
||||
port 6379
|
||||
appendonly yes
|
|
@ -3,6 +3,7 @@
|
|||
namespace Socialbox\Classes\CliCommands;
|
||||
|
||||
use Exception;
|
||||
use LogLib\Log;
|
||||
use PDOException;
|
||||
use Socialbox\Abstracts\CacheLayer;
|
||||
use Socialbox\Classes\Configuration;
|
||||
|
@ -23,7 +24,7 @@
|
|||
*/
|
||||
public static function execute(array $args): int
|
||||
{
|
||||
if(Configuration::getInstanceConfiguration()->isEnabled() === false && !isset($args['force']))
|
||||
if(Configuration::getInstanceConfiguration()->isEnabled() === false && !isset($args['force']) && getenv('SB_MODE') !== 'automated')
|
||||
{
|
||||
$required_configurations = [
|
||||
'database.host', 'database.port', 'database.username', 'database.password', 'database.name',
|
||||
|
@ -47,9 +48,170 @@
|
|||
Logger::getLogger()->info(' configlib --conf socialbox -e nano');
|
||||
Logger::getLogger()->info('Or manually at:');
|
||||
Logger::getLogger()->info(sprintf(' %s', Configuration::getConfigurationLib()->getPath()));
|
||||
Logger::getLogger()->info('Automated Setup Procedure is done using environment variables:');
|
||||
Logger::getLogger()->info(' - SB_MODE=automated');
|
||||
Logger::getLogger()->info(' - SB_INSTANCE_DOMAIN=example.com => The Domain Name');
|
||||
Logger::getLogger()->info(' - SB_INSTANCE_RPC_ENDPOINT=http://localhost => The RPC Endpoint, must be publicly accessible');
|
||||
Logger::getLogger()->info(' - SB_DATABASE_HOST=localhost => The MySQL Host');
|
||||
Logger::getLogger()->info(' - SB_DATABASE_PORT=3306 => The MySQL Port');
|
||||
Logger::getLogger()->info(' - SB_DATABASE_USER=root => The MySQL Username');
|
||||
Logger::getLogger()->info(' - SB_DATABASE_PASSWORD=pass => The MySQL Password');
|
||||
Logger::getLogger()->info(' - SB_DATABASE_DATABASE=socialbox => The MySQL Database');
|
||||
Logger::getLogger()->info(' - SB_CACHE_ENGINE=redis => The Cache engine to use, supports redis, memcached or null');
|
||||
Logger::getLogger()->info(' - SB_CACHE_HOST=localhost => The Cache Host');
|
||||
Logger::getLogger()->info(' - SB_CACHE_PORT=6379 => The Cache Port');
|
||||
Logger::getLogger()->info(' - SB_CACHE_PASSWORD=pass => The Cache Password');
|
||||
Logger::getLogger()->info(' - SB_CACHE_DATABASE=0 => The Cache Database');
|
||||
Logger::getLogger()->info(' - SB_STORAGE_PATH=/etc/socialbox => The Storage Path');
|
||||
Logger::getLogger()->info('Anything omitted will be null or empty in the configuration');
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Overwrite the configuration if the automated setup procedure is detected
|
||||
// This is useful for CI/CD pipelines & Docker
|
||||
if(getenv('SB_MODE') === 'automated')
|
||||
{
|
||||
Logger::getLogger()->info('Automated Setup Procedure is detected');
|
||||
|
||||
if(getenv('SB_INSTANCE_DOMAIN') !== false)
|
||||
{
|
||||
Configuration::getConfigurationLib()->set('instance.domain', getenv('SB_INSTANCE_DOMAIN'));
|
||||
Logger::getLogger()->info('Set instance.domain to ' . getenv('SB_INSTANCE_DOMAIN'));
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::getLogger()->warning('instance.domain is required but was not set, expected SB_INSTANCE_DOMAIN environment variable');
|
||||
}
|
||||
|
||||
if(getenv('SB_INSTANCE_RPC_ENDPOINT') !== false)
|
||||
{
|
||||
Configuration::getConfigurationLib()->set('instance.rpc_endpoint', getenv('SB_INSTANCE_RPC_ENDPOINT'));
|
||||
Logger::getLogger()->info('Set instance.rpc_endpoint to ' . getenv('SB_INSTANCE_RPC_ENDPOINT'));
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::getLogger()->warning('instance.rpc_endpoint is required but was not set, expected SB_INSTANCE_RPC_ENDPOINT environment variable');
|
||||
Configuration::getConfigurationLib()->set('instance.rpc_endpoint', 'http://127.0.0.0/');
|
||||
Logger::getLogger()->info('Set instance.rpc_endpoint to http://127.0.0.0/');
|
||||
}
|
||||
|
||||
if(getenv('SB_STORAGE_PATH') !== false)
|
||||
{
|
||||
Configuration::getConfigurationLib()->set('storage.path', getenv('SB_STORAGE_PATH'));
|
||||
Logger::getLogger()->info('Set storage.path to ' . getenv('SB_STORAGE_PATH'));
|
||||
}
|
||||
else
|
||||
{
|
||||
Configuration::getConfigurationLib()->set('storage.path', '/etc/socialbox');
|
||||
Logger::getLogger()->info('storage.path was not set, defaulting to /etc/socialbox');
|
||||
}
|
||||
|
||||
if(getenv('SB_DATABASE_HOST') !== false)
|
||||
{
|
||||
Configuration::getConfigurationLib()->set('database.host', getenv('SB_DATABASE_HOST'));
|
||||
Logger::getLogger()->info('Set database.host to ' . getenv('SB_DATABASE_HOST'));
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::getLogger()->warning('database.host is required but was not set, expected SB_DATABASE_HOST environment variable');
|
||||
}
|
||||
|
||||
if(getenv('SB_DATABASE_PORT') !== false)
|
||||
{
|
||||
Configuration::getConfigurationLib()->set('database.port', getenv('SB_DATABASE_PORT'));
|
||||
Logger::getLogger()->info('Set database.port to ' . getenv('SB_DATABASE_PORT'));
|
||||
}
|
||||
|
||||
if(getenv('SB_DATABASE_USERNAME') !== false)
|
||||
{
|
||||
Configuration::getConfigurationLib()->set('database.username', getenv('SB_DATABASE_USERNAME'));
|
||||
Logger::getLogger()->info('Set database.username to ' . getenv('SB_DATABASE_USERNAME'));
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::getLogger()->warning('database.username is required but was not set, expected SB_DATABASE_USERNAME environment variable');
|
||||
}
|
||||
|
||||
if(getenv('SB_DATABASE_PASSWORD') !== false)
|
||||
{
|
||||
Configuration::getConfigurationLib()->set('database.password', getenv('SB_DATABASE_PASSWORD'));
|
||||
Logger::getLogger()->info('Set database.password to ' . getenv('SB_DATABASE_PASSWORD'));
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::getLogger()->warning('database.password is required but was not set, expected SB_DATABASE_PASSWORD environment variable');
|
||||
}
|
||||
|
||||
if(getenv('SB_DATABASE_NAME') !== false)
|
||||
{
|
||||
Configuration::getConfigurationLib()->set('database.name', getenv('SB_DATABASE_NAME'));
|
||||
Logger::getLogger()->info('Set database.name to ' . getenv('SB_DATABASE_NAME'));
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::getLogger()->warning('database.name is required but was not set, expected SB_DATABASE_NAME environment variable');
|
||||
}
|
||||
|
||||
if(getenv('SB_CACHE_ENABLED') !== false)
|
||||
{
|
||||
Configuration::getConfigurationLib()->set('cache.enabled', true);
|
||||
Logger::getLogger()->info('Set cache.engine to true');
|
||||
}
|
||||
else
|
||||
{
|
||||
Configuration::getConfigurationLib()->set('cache.enabled', false);
|
||||
Logger::getLogger()->info('cache.engine is was not set, defaulting to false');
|
||||
}
|
||||
|
||||
|
||||
if(getenv('SB_CACHE_ENGINE') !== false)
|
||||
{
|
||||
Configuration::getConfigurationLib()->set('cache.engine', getenv('SB_CACHE_ENGINE'));
|
||||
Logger::getLogger()->info('Set cache.engine to ' . getenv('SB_CACHE_ENGINE'));
|
||||
}
|
||||
|
||||
if(getenv('SB_CACHE_HOST') !== false)
|
||||
{
|
||||
Configuration::getConfigurationLib()->set('cache.host', getenv('SB_CACHE_HOST'));
|
||||
Logger::getLogger()->info('Set cache.host to ' . getenv('SB_CACHE_HOST'));
|
||||
}
|
||||
elseif(Configuration::getCacheConfiguration()->isEnabled())
|
||||
{
|
||||
Logger::getLogger()->warning('cache.host is required but was not set, expected SB_CACHE_HOST environment variable');
|
||||
}
|
||||
|
||||
if(getenv('SB_CACHE_PORT') !== false)
|
||||
{
|
||||
Configuration::getConfigurationLib()->set('cache.port', getenv('SB_CACHE_PORT'));
|
||||
Logger::getLogger()->info('Set cache.port to ' . getenv('SB_CACHE_PORT'));
|
||||
}
|
||||
|
||||
if(getenv('SB_CACHE_PASSWORD') !== false)
|
||||
{
|
||||
Configuration::getConfigurationLib()->set('cache.password', getenv('SB_CACHE_PASSWORD'));
|
||||
Logger::getLogger()->info('Set cache.password to ' . getenv('SB_CACHE_PASSWORD'));
|
||||
}
|
||||
elseif(Configuration::getCacheConfiguration()->isEnabled())
|
||||
{
|
||||
Logger::getLogger()->warning('cache.password is required but was not set, expected SB_CACHE_PASSWORD environment variable');
|
||||
}
|
||||
|
||||
if(getenv('SB_CACHE_DATABASE') !== false)
|
||||
{
|
||||
Configuration::getConfigurationLib()->set('cache.database', getenv('SB_CACHE_DATABASE'));
|
||||
Logger::getLogger()->info('Set cache.database to ' . getenv('SB_CACHE_DATABASE'));
|
||||
}
|
||||
elseif(Configuration::getCacheConfiguration()->isEnabled())
|
||||
{
|
||||
Configuration::getConfigurationLib()->set('cache.database', 0);
|
||||
Logger::getLogger()->info('cache.database defaulting to 0');
|
||||
}
|
||||
|
||||
Configuration::getConfigurationLib()->save(); // Save
|
||||
Configuration::reload(); // Reload
|
||||
}
|
||||
|
||||
if(Configuration::getInstanceConfiguration()->getDomain() === null)
|
||||
{
|
||||
Logger::getLogger()->error('instance.domain is required but was not set');
|
||||
|
@ -140,14 +302,24 @@
|
|||
catch (CryptographyException $e)
|
||||
{
|
||||
Logger::getLogger()->error('Failed to generate encryption records due to a cryptography exception', $e);
|
||||
return 1;
|
||||
}
|
||||
catch (DatabaseOperationException $e)
|
||||
{
|
||||
Logger::getLogger()->error('Failed to generate encryption records due to a database error', $e);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// TODO: Create a host peer here?
|
||||
Logger::getLogger()->info('Socialbox has been initialized successfully');
|
||||
if(getenv('SB_MODE') === 'automated')
|
||||
{
|
||||
Configuration::getConfigurationLib()->set('instance.enabled', true);
|
||||
Configuration::getConfigurationLib()->save(); // Save
|
||||
|
||||
Logger::getLogger()->info('Automated Setup Procedure is complete, requests to the RPC server ' . Configuration::getInstanceConfiguration()->getRpcEndpoint() . ' are now accepted');
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -80,4 +80,15 @@
|
|||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs and retrieves the Data Source Name (DSN) string.
|
||||
*
|
||||
* @return string The DSN string for the database connection.
|
||||
*/
|
||||
public function getDsn(): string
|
||||
{
|
||||
return sprintf('mysql:host=%s;dbname=%s;port=%s;charset=utf8mb4', $this->host, $this->name, $this->port);
|
||||
}
|
||||
}
|
|
@ -1,39 +1,41 @@
|
|||
<?php
|
||||
|
||||
namespace Socialbox\Classes;
|
||||
namespace Socialbox\Classes;
|
||||
|
||||
use PDO;
|
||||
use PDOException;
|
||||
use Socialbox\Exceptions\DatabaseOperationException;
|
||||
use PDO;
|
||||
use PDOException;
|
||||
use Socialbox\Classes\Configuration\DatabaseConfiguration;
|
||||
use Socialbox\Exceptions\DatabaseOperationException;
|
||||
|
||||
class Database
|
||||
{
|
||||
private static ?PDO $instance = null;
|
||||
|
||||
/**
|
||||
* @return PDO
|
||||
* @throws DatabaseOperationException
|
||||
*/
|
||||
public static function getConnection(): PDO
|
||||
class Database
|
||||
{
|
||||
if (self::$instance === null)
|
||||
{
|
||||
try
|
||||
{
|
||||
$dsn = 'mysql:host=127.0.0.1;dbname=socialbox;port=3306;charset=utf8mb4';
|
||||
self::$instance = new PDO($dsn, 'root', 'root');
|
||||
private static ?PDO $instance = null;
|
||||
|
||||
// Set some common PDO attributes for better error handling
|
||||
self::$instance->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
self::$instance->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
|
||||
}
|
||||
catch (PDOException $e)
|
||||
/**
|
||||
* @return PDO
|
||||
* @throws DatabaseOperationException
|
||||
*/
|
||||
public static function getConnection(): PDO
|
||||
{
|
||||
if (self::$instance === null)
|
||||
{
|
||||
throw new DatabaseOperationException('Failed to connect to the database', $e);
|
||||
$dsn = Configuration::getDatabaseConfiguration()->getDsn();
|
||||
|
||||
try
|
||||
{
|
||||
self::$instance = new PDO($dsn, Configuration::getDatabaseConfiguration()->getUsername(), Configuration::getDatabaseConfiguration()->getPassword());
|
||||
|
||||
// Set some common PDO attributes for better error handling
|
||||
self::$instance->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
self::$instance->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
|
||||
}
|
||||
catch (PDOException $e)
|
||||
{
|
||||
throw new DatabaseOperationException('Failed to connect to the database using ' . $dsn, $e);
|
||||
}
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
create table authentication_passwords
|
||||
(
|
||||
peer_uuid varchar(36) not null comment 'The Universal Unique Identifier for the peer that is associated with this password record'
|
||||
primary key comment 'The primary unique index of the peer uuid',
|
||||
iv mediumtext not null comment 'The Initial Vector of the password record',
|
||||
encrypted_password mediumtext not null comment 'The encrypted password data',
|
||||
encrypted_tag mediumtext not null comment 'The encrypted tag of the password record',
|
||||
updated timestamp default current_timestamp() not null comment 'The Timestamp for when this record was last updated',
|
||||
constraint authentication_passwords_peer_uuid_uindex
|
||||
unique (peer_uuid) comment 'The primary unique index of the peer uuid',
|
||||
constraint authentication_passwords_registered_peers_uuid_fk
|
||||
foreign key (peer_uuid) references registered_peers (uuid)
|
||||
on update cascade on delete cascade
|
||||
)
|
||||
comment 'Table for housing authentication passwords for registered peers';
|
||||
|
||||
create index authentication_passwords_updated_index
|
||||
on authentication_passwords (updated)
|
||||
comment 'The index of the of the updated column of the record';
|
||||
|
24
src/Socialbox/Classes/Resources/database/captcha_images.sql
Normal file
24
src/Socialbox/Classes/Resources/database/captcha_images.sql
Normal file
|
@ -0,0 +1,24 @@
|
|||
create table captcha_images
|
||||
(
|
||||
uuid varchar(36) default uuid() not null comment 'The Unique Universal Identifier of the captcha record'
|
||||
primary key comment 'The Unique index for the UUID column',
|
||||
peer_uuid varchar(36) not null comment 'The UUID of the peer that is associated with this captcha challenge',
|
||||
status enum ('UNSOLVED', 'SOLVED') default 'UNSOLVED' not null comment 'The status of the current captcha',
|
||||
answer varchar(8) null comment 'The current answer for the captcha',
|
||||
answered timestamp null comment 'The Timestamp for when this captcha was answered',
|
||||
created timestamp default current_timestamp() not null comment 'The Timestamp for when this captcha record was created',
|
||||
constraint captchas_peer_uuid_uindex
|
||||
unique (peer_uuid) comment 'The Primary Unique Index for the peer UUID',
|
||||
constraint captchas_registered_peers_uuid_fk
|
||||
foreign key (peer_uuid) references registered_peers (uuid)
|
||||
on update cascade on delete cascade
|
||||
);
|
||||
|
||||
create index captchas_status_index
|
||||
on captcha_images (status)
|
||||
comment 'The Index for the captcha status';
|
||||
|
||||
create index captchas_uuid_index
|
||||
on captcha_images (uuid)
|
||||
comment 'The Unique index for the UUID column';
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
create table encryption_records
|
||||
(
|
||||
data mediumtext not null comment 'The data column',
|
||||
iv mediumtext not null comment 'The initialization vector column',
|
||||
tag mediumtext not null comment 'The authentication tag used to verify if the data was tampered'
|
||||
)
|
||||
comment 'Table for housing encryption records for the server';
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
create table external_sessions
|
||||
(
|
||||
uuid varchar(36) default uuid() not null comment 'The UUID of the session for the external connection'
|
||||
primary key comment 'The Unique Primary Index for the session UUID',
|
||||
peer_uuid varchar(36) not null comment 'The peer UUID that opened the connection',
|
||||
session_uuid varchar(36) null comment 'The UUID of the parent session responsible for this external session',
|
||||
server varchar(255) null comment 'The domain of the remote server that ths external session is authorized for',
|
||||
created timestamp default current_timestamp() not null comment 'The Timestamp for when this record was created',
|
||||
last_used timestamp default current_timestamp() not null comment 'The Timestamp for when this session was last used',
|
||||
constraint external_sessions_uuid_uindex
|
||||
unique (uuid) comment 'The Unique Primary Index for the session UUID',
|
||||
constraint external_sessions_registered_peers_uuid_fk
|
||||
foreign key (peer_uuid) references registered_peers (uuid)
|
||||
on update cascade on delete cascade,
|
||||
constraint external_sessions_sessions_uuid_fk
|
||||
foreign key (session_uuid) references sessions (uuid)
|
||||
)
|
||||
comment 'Table for housing external sessions from local to remote servers';
|
||||
|
||||
create index external_sessions_created_index
|
||||
on external_sessions (created)
|
||||
comment 'The Index for the created column';
|
||||
|
||||
create index external_sessions_last_used_index
|
||||
on external_sessions (last_used)
|
||||
comment 'The inex for the last used column';
|
||||
|
||||
create index external_sessions_peer_uuid_index
|
||||
on external_sessions (peer_uuid)
|
||||
comment 'The Index for the peer UUID';
|
||||
|
||||
create index external_sessions_session_uuid_index
|
||||
on external_sessions (session_uuid)
|
||||
comment 'The index for the original session uuid';
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
create table password_authentication
|
||||
(
|
||||
peer_uuid varchar(36) not null comment 'The Primary unique Index for the peer UUID'
|
||||
primary key,
|
||||
value varchar(128) not null comment 'The hash value of the pasword',
|
||||
updated timestamp default current_timestamp() not null comment 'The Timestamp for when this record was last updated',
|
||||
constraint password_authentication_peer_uuid_uindex
|
||||
unique (peer_uuid) comment 'The Primary unique Index for the peer UUID',
|
||||
constraint password_authentication_registered_peers_uuid_fk
|
||||
foreign key (peer_uuid) references registered_peers (uuid)
|
||||
on update cascade on delete cascade
|
||||
)
|
||||
comment 'Table for housing password authentications associated with peers';
|
||||
|
||||
create index password_authentication_updated_index
|
||||
on password_authentication (updated)
|
||||
comment 'The Indefor the updated timestamp';
|
||||
|
|
@ -1,20 +1,39 @@
|
|||
create table registered_peers
|
||||
(
|
||||
uuid varchar(36) default uuid() not null comment 'The Primary index for the peer uuid'
|
||||
uuid varchar(36) default uuid() not null comment 'The Primary index for the peer uuid'
|
||||
primary key,
|
||||
username varchar(255) not null comment 'The Unique username associated with the peer',
|
||||
flags text null comment 'Comma seprted flags associated with the peer',
|
||||
registered timestamp default current_timestamp() not null comment 'The Timestamp for when the peer was registered on the network',
|
||||
constraint registered_peers_pk_2
|
||||
unique (username) comment 'The unique username for the peer',
|
||||
constraint registered_peers_username_uindex
|
||||
unique (username) comment 'The unique username for the peer',
|
||||
username varchar(255) not null comment 'The Unique username associated with the peer',
|
||||
server varchar(255) default 'host' not null comment 'The server that this peer is registered to',
|
||||
display_name varchar(255) null comment 'Optional. The Non-Unique Display name of the peer',
|
||||
display_picture varchar(36) null comment 'The UUID of the display picture that is used, null if none is set.',
|
||||
flags text null comment 'Comma seprted flags associated with the peer',
|
||||
enabled tinyint(1) default 0 not null comment 'Boolean column to indicate if this account is Enabled, by default it''s Disabled until the account is verified.',
|
||||
updated timestamp default current_timestamp() not null comment 'The Timestamp for when this record was last updated',
|
||||
created timestamp default current_timestamp() not null comment 'The Timestamp for when the peer was registered on the network',
|
||||
constraint registered_peers_server_username_uindex
|
||||
unique (server, username) comment 'The Unique Username + Server Index Pair',
|
||||
constraint registered_peers_uuid_uindex
|
||||
unique (uuid) comment 'The Primary index for the peer uuid'
|
||||
)
|
||||
comment 'Table for housing registered peers under this network';
|
||||
|
||||
create index registered_peers_enabled_index
|
||||
on registered_peers (enabled)
|
||||
comment 'The index of the enabled column for registered peers';
|
||||
|
||||
create index registered_peers_registered_index
|
||||
on registered_peers (created)
|
||||
comment 'The Index for the reigstered column of the peer';
|
||||
|
||||
create index registered_peers_server_index
|
||||
on registered_peers (server)
|
||||
comment 'The Index for the peer''s server';
|
||||
|
||||
create index registered_peers_updated_index
|
||||
on registered_peers (updated)
|
||||
comment 'The Index for the update column';
|
||||
|
||||
create index registered_peers_username_index
|
||||
on registered_peers (username)
|
||||
comment 'The index for the registered username';
|
||||
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
create table resolved_servers
|
||||
(
|
||||
domain varchar(512) not null comment 'The domain name'
|
||||
primary key comment 'Unique Index for the server domain',
|
||||
endpoint text not null comment 'The endpoint of the RPC server',
|
||||
public_key text not null comment 'The Public Key of the server',
|
||||
updated timestamp default current_timestamp() not null comment 'The TImestamp for when this record was last updated',
|
||||
constraint resolved_servers_domain_uindex
|
||||
unique (domain) comment 'Unique Index for the server domain'
|
||||
)
|
||||
comment 'A table for housing DNS resolutions';
|
||||
|
|
@ -1,21 +1,26 @@
|
|||
create table sessions
|
||||
(
|
||||
uuid varchar(36) default uuid() not null comment 'The Unique Primary index for the session UUID'
|
||||
uuid varchar(36) default uuid() not null comment 'The Unique Primary index for the session UUID'
|
||||
primary key,
|
||||
authenticated_peer_uuid varchar(36) null comment 'The peer the session is authenticated as, null if the session isn''t authenticated',
|
||||
public_key blob not null comment 'The client''s public key provided when creating the session',
|
||||
state enum ('ACTIVE', 'EXPIRED', 'CLOSED') default 'ACTIVE' not null comment 'The status of the session',
|
||||
created timestamp default current_timestamp() not null comment 'The Timestamp for when the session was last created',
|
||||
last_request timestamp null comment 'The Timestamp for when the last request was made using this session',
|
||||
peer_uuid varchar(36) not null comment 'The peer the session is identified as, null if the session isn''t identified as a peer',
|
||||
client_name varchar(256) not null comment 'The name of the client that is using this session',
|
||||
client_version varchar(16) not null comment 'The version of the client',
|
||||
authenticated tinyint(1) default 0 not null comment 'Indicates if the session is currently authenticated as the peer',
|
||||
public_key text not null comment 'The client''s public key provided when creating the session',
|
||||
state enum ('AWAITING_DHE', 'ACTIVE', 'CLOSED', 'EXPIRED') default 'AWAITING_DHE' not null comment 'The status of the session',
|
||||
encryption_key text null comment 'The key used for encryption that is obtained through a DHE',
|
||||
flags text null comment 'The current flags that is set to the session',
|
||||
created timestamp default current_timestamp() not null comment 'The Timestamp for when the session was last created',
|
||||
last_request timestamp null comment 'The Timestamp for when the last request was made using this session',
|
||||
constraint sessions_uuid_uindex
|
||||
unique (uuid) comment 'The Unique Primary index for the session UUID',
|
||||
constraint sessions_registered_peers_uuid_fk
|
||||
foreign key (authenticated_peer_uuid) references registered_peers (uuid)
|
||||
foreign key (peer_uuid) references registered_peers (uuid)
|
||||
on update cascade on delete cascade
|
||||
);
|
||||
|
||||
create index sessions_authenticated_peer_index
|
||||
on sessions (authenticated_peer_uuid)
|
||||
on sessions (peer_uuid)
|
||||
comment 'The Index for the authenticated peer column';
|
||||
|
||||
create index sessions_created_index
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
create table variables
|
||||
(
|
||||
name varchar(255) not null comment 'The name of the variable'
|
||||
primary key comment 'The unique index for the variable name',
|
||||
value text null comment 'The value of the variable',
|
||||
`read_only` tinyint(1) default 0 not null comment 'Boolean indicator if the variable is read only',
|
||||
created timestamp default current_timestamp() not null comment 'The Timestamp for when this record was created',
|
||||
updated timestamp null comment 'The Timestamp for when this record was last updated',
|
||||
name varchar(255) not null comment 'The unique index for the variable name'
|
||||
primary key,
|
||||
value text null comment 'The value of the variable',
|
||||
read_only tinyint(1) default 0 not null comment 'Boolean indicator if the variable is read only',
|
||||
created timestamp default current_timestamp() not null comment 'The Timestamp for when this record was created',
|
||||
updated timestamp null comment 'The Timestamp for when this record was last updated',
|
||||
constraint variables_name_uindex
|
||||
unique (name) comment 'The unique index for the variable name'
|
||||
);
|
||||
|
||||
|
|
|
@ -1,38 +1,44 @@
|
|||
<?php
|
||||
|
||||
namespace Socialbox\Enums;
|
||||
namespace Socialbox\Enums;
|
||||
|
||||
enum DatabaseObjects : string
|
||||
{
|
||||
case PASSWORD_AUTHENTICATION = 'password_authentication.sql';
|
||||
case REGISTERED_PEERS = 'registered_peers.sql';
|
||||
case SESSIONS = 'sessions.sql';
|
||||
case VARIABLES = 'variables.sql';
|
||||
|
||||
/**
|
||||
* Returns the priority of the database object
|
||||
*
|
||||
* @return int The priority of the database object
|
||||
*/
|
||||
public function getPriority(): int
|
||||
enum DatabaseObjects : string
|
||||
{
|
||||
return match ($this)
|
||||
case VARIABLES = 'variables.sql';
|
||||
case ENCRYPTION_RECORDS = 'encryption_records.sql';
|
||||
case RESOLVED_SERVERS = 'resolved_servers.sql';
|
||||
|
||||
case REGISTERED_PEERS = 'registered_peers.sql';
|
||||
|
||||
case AUTHENTICATION_PASSWORDS = 'authentication_passwords.sql';
|
||||
case CAPTCHA_IMAGES = 'captcha_images.sql';
|
||||
case SESSIONS = 'sessions.sql';
|
||||
case EXTERNAL_SESSIONS = 'external_sessions.sql';
|
||||
|
||||
/**
|
||||
* Returns the priority of the database object
|
||||
*
|
||||
* @return int The priority of the database object
|
||||
*/
|
||||
public function getPriority(): int
|
||||
{
|
||||
self::VARIABLES => 0,
|
||||
self::REGISTERED_PEERS => 1,
|
||||
self::PASSWORD_AUTHENTICATION, self::SESSIONS => 2,
|
||||
};
|
||||
}
|
||||
return match ($this)
|
||||
{
|
||||
self::VARIABLES, self::ENCRYPTION_RECORDS, self::RESOLVED_SERVERS => 0,
|
||||
self::REGISTERED_PEERS => 1,
|
||||
self::AUTHENTICATION_PASSWORDS, self::CAPTCHA_IMAGES, self::SESSIONS, self::EXTERNAL_SESSIONS => 2,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of cases ordered by their priority.
|
||||
*
|
||||
* @return array The array of cases sorted by their priority.
|
||||
*/
|
||||
public static function casesOrdered(): array
|
||||
{
|
||||
$cases = self::cases();
|
||||
usort($cases, fn($a, $b) => $a->getPriority() <=> $b->getPriority());
|
||||
return $cases;
|
||||
/**
|
||||
* Returns an array of cases ordered by their priority.
|
||||
*
|
||||
* @return array The array of cases sorted by their priority.
|
||||
*/
|
||||
public static function casesOrdered(): array
|
||||
{
|
||||
$cases = self::cases();
|
||||
usort($cases, fn($a, $b) => $a->getPriority() <=> $b->getPriority());
|
||||
return $cases;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
47
supervisord.conf
Normal file
47
supervisord.conf
Normal file
|
@ -0,0 +1,47 @@
|
|||
[supervisord]
|
||||
logfile=/var/logd.log
|
||||
logfile_maxbytes=50MB
|
||||
logfile_backups=10
|
||||
loglevel=info
|
||||
user=root
|
||||
pidfile=/var/run/supervisord.pid
|
||||
umask=022
|
||||
nodaemon=true
|
||||
minfds=1024
|
||||
minprocs=200
|
||||
|
||||
[program:php-fpm]
|
||||
command=/usr/local/sbin/php-fpm --nodaemonize
|
||||
autostart=true
|
||||
autorestart=true
|
||||
priority=20
|
||||
stdout_logfile=/var/log/fpm.log
|
||||
stderr_logfile=/var/log/fpm_error.log
|
||||
stdout_logfile_maxbytes=20MB
|
||||
stdout_logfile_backups=5
|
||||
stderr_logfile_maxbytes=20MB
|
||||
stderr_logfile_backups=5
|
||||
|
||||
[program:nginx]
|
||||
command=/usr/sbin/nginx -g "daemon off;" -c /etc/nginx/nginx.conf
|
||||
autostart=true
|
||||
autorestart=true
|
||||
priority=10
|
||||
stdout_logfile=/var/log/nginx.log
|
||||
stderr_logfile=/var/log/nginx_error.log
|
||||
stdout_logfile_maxbytes=20MB
|
||||
stdout_logfile_backups=5
|
||||
stderr_logfile_maxbytes=20MB
|
||||
stderr_logfile_backups=5
|
||||
|
||||
[program:cron]
|
||||
command=cron -f -L 15
|
||||
autostart=true
|
||||
autorestart=true
|
||||
priority=30
|
||||
stdout_logfile=/var/log/cron.log
|
||||
stderr_logfile=/var/log/cron_error.log
|
||||
stdout_logfile_maxbytes=20MB
|
||||
stdout_logfile_backups=5
|
||||
stderr_logfile_maxbytes=20MB
|
||||
stderr_logfile_backups=5
|
Loading…
Add table
Reference in a new issue