diff --git a/.env.example b/.env.example new file mode 100644 index 00000000..4af6c61a --- /dev/null +++ b/.env.example @@ -0,0 +1,60 @@ +# Example environment variables for the vichan imageboard Docker Compose setup. +# Copy this file to `.env` and customize values as needed. +# Do not commit `.env` with sensitive data to version control. + +# General Settings +INSTANCE=0 + +# Web Service (Nginx) Settings +# SSL_CERT_PATH=/path/to/cert.pem +# SSL_KEY_PATH=/path/to/key.pem + +# PHP Service Settings +## Database settings +VICHAN_MYSQL_HOST=db +VICHAN_MYSQL_USER=vichan +VICHAN_MYSQL_NAME=vichan +VICHAN_MYSQL_PASSWORD=vichan! + +## Security +VICHAN_SECURE_LOGIN_ONLY=0 + +## Cookies +VICHAN_COOKIES_MOD=mod + +## Flood Control +VICHAN_FLOOD_TIME=30 +VICHAN_FLOOD_TIME_IP=120 +VICHAN_FLOOD_TIME_SAME=3600 +VICHAN_MAX_BODY=1800 +VICHAN_REPLY_LIMIT=250 +VICHAN_MAX_LINKS=20 + +## Images +VICHAN_IMAGES_MAX_FILESIZE=10485760 +VICHAN_IMAGES_THUMB_WIDTH=250 +VICHAN_IMAGES_THUMB_HEIGHT=250 +VICHAN_IMAGES_MAX_WIDTH=10000 +VICHAN_IMAGES_MAX_HEIGHT=10000 + +## Display +VICHAN_DISPLAY_THREADS_PER_PAGE=10 +VICHAN_DISPLAY_MAX_PAGES=11 +VICHAN_DISPLAY_THREADS_PREVIEW=5 + +## Directories +VICHAN_DIRECTORIES_ROOT=/ + + +# Database Service (MariaDB) Settings +MYSQL_DATABASE=vichan +MYSQL_USER=vichan +MYSQL_PASSWORD=vichan! +MYSQL_ROOT_PASSWORD=vichan!! + + +# Cache Settings +VICHAN_CACHE_ENGINE=redis +VICHAN_CACHE_HOST=redis +VICHAN_CACHE_PORT=6379 +VICHAN_CACHE_PASSWORD=redis! diff --git a/.gitignore b/.gitignore index 5e0ab052..e8d786e6 100644 --- a/.gitignore +++ b/.gitignore @@ -29,6 +29,7 @@ thumbs.db Icon? Thumbs.db +.env *.patch *.diff *.rej diff --git a/compose.yml b/compose.yml index 4b87e0b6..5666d154 100644 --- a/compose.yml +++ b/compose.yml @@ -1,18 +1,22 @@ services: - #nginx webserver + php 8.x web: build: context: . dockerfile: ./docker/nginx/Dockerfile - ports: - - "9090:80" - depends_on: - - db + container_name: vichan_web + restart: unless-stopped volumes: - ./local-instances/${INSTANCE:-0}/www:/var/www/html - ./docker/nginx/vichan.conf:/etc/nginx/conf.d/default.conf - ./docker/nginx/nginx.conf:/etc/nginx/nginx.conf - ./docker/nginx/proxy.conf:/etc/nginx/conf.d/proxy.conf +# - ./docker/nginx/ssl:/etc/nginx/ssl # optional For SSL + ports: + - "9080:80" +# - "9081:443" # optional for SSL + depends_on: + - db + - php links: - php @@ -20,21 +24,77 @@ services: build: context: . dockerfile: ./docker/php/Dockerfile + container_name: vichan_php + restart: unless-stopped volumes: - ./local-instances/${INSTANCE:-0}/www:/var/www - ./docker/php/www.conf:/usr/local/etc/php-fpm.d/www.conf - ./docker/php/jit.ini:/usr/local/etc/php/conf.d/jit.ini - - #MySQL Service - db: - image: mysql:8.0.35 - container_name: db - restart: unless-stopped - tty: true - ports: - - "3306:3306" + - ./docker/php/php.ini:/usr/local/etc/php/php.ini environment: - MYSQL_DATABASE: vichan - MYSQL_ROOT_PASSWORD: password + # Database settings + VICHAN_MYSQL_HOST: ${VICHAN_MYSQL_HOST} + VICHAN_MYSQL_USER: ${VICHAN_MYSQL_USER} + VICHAN_MYSQL_NAME: ${VICHAN_MYSQL_NAME} + VICHAN_MYSQL_PASSWORD: ${VICHAN_MYSQL_PASSWORD} + # Security + VICHAN_SECURE_LOGIN_ONLY: ${VICHAN_SECURE_LOGIN_ONLY} + # Cache settings + VICHAN_CACHE_ENGINE: ${VICHAN_CACHE_ENGINE} + VICHAN_CACHE_HOST: ${VICHAN_CACHE_HOST} + VICHAN_CACHE_PORT: ${VICHAN_CACHE_PORT} + VICHAN_CACHE_PASSWORD: ${VICHAN_CACHE_PASSWORD} + # Cookies + VICHAN_COOKIES_MOD: ${VICHAN_COOKIES_MOD} + # Flood Control + VICHAN_FLOOD_TIME: ${VICHAN_FLOOD_TIME} + VICHAN_FLOOD_TIME_IP: ${VICHAN_FLOOD_TIME_IP} + VICHAN_FLOOD_TIME_SAME: ${VICHAN_FLOOD_TIME_SAME} + VICHAN_MAX_BODY: ${VICHAN_MAX_BODY} + VICHAN_REPLY_LIMIT: ${VICHAN_REPLY_LIMIT} + VICHAN_MAX_LINKS: ${VICHAN_MAX_LINKS} + # Images + VICHAN_IMAGES_MAX_FILESIZE: ${VICHAN_IMAGES_MAX_FILESIZE} + VICHAN_IMAGES_THUMB_WIDTH: ${VICHAN_IMAGES_THUMB_WIDTH} + VICHAN_IMAGES_THUMB_HEIGHT: ${VICHAN_IMAGES_THUMB_HEIGHT} + VICHAN_IMAGES_MAX_WIDTH: ${VICHAN_IMAGES_MAX_WIDTH} + VICHAN_IMAGES_MAX_HEIGHT: ${VICHAN_IMAGES_MAX_HEIGHT} + # Display + VICHAN_DISPLAY_THREADS_PER_PAGE: ${VICHAN_DISPLAY_THREADS_PER_PAGE} + VICHAN_DISPLAY_MAX_PAGES: ${VICHAN_DISPLAY_MAX_PAGES} + VICHAN_DISPLAY_THREADS_PREVIEW: ${VICHAN_DISPLAY_THREADS_PREVIEW} + # Directories + VICHAN_DIRECTORIES_ROOT: ${VICHAN_DIRECTORIES_ROOT} + depends_on: + - db + + db: + image: mysql:lts + # image: mariadb:lts # optional for more higher performance + container_name: vichan_db + restart: unless-stopped volumes: - - ./local-instances/${INSTANCE:-0}/mysql:/var/lib/mysql + - ./local-instances/${INSTANCE:-0}/db:/var/lib/mysql + # ports: + # - "9082:3306" # optional for external access + environment: + MYSQL_DATABASE: ${MYSQL_DATABASE} + MYSQL_USER: ${MYSQL_USER} + MYSQL_PASSWORD: ${MYSQL_PASSWORD} + MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} + + redis: + image: redis:latest + container_name: vichan_redis + restart: unless-stopped + volumes: + - ./local-instances/${INSTANCE:-0}/redis:/data + environment: + REDIS_PASSWORD: ${VICHAN_CACHE_PASSWORD} + command: redis-server --requirepass ${VICHAN_CACHE_PASSWORD} + healthcheck: + test: ["CMD", "redis-cli", "-a", "${VICHAN_CACHE_PASSWORD}", "ping"] + interval: 10s + timeout: 5s + retries: 5 + start_period: 30s \ No newline at end of file diff --git a/docker/doc.md b/docker/doc.md index 051ae56e..37f36063 100644 --- a/docker/doc.md +++ b/docker/doc.md @@ -1,20 +1,160 @@ -The `php-fpm` process runs containerized. -The php application always uses `/var/www` as it's work directory and home folder, and if `/var/www` is bind mounted it -is necessary to adjust the path passed via FastCGI to `php-fpm` by changing the root directory to `/var/www`. -This can achieved in nginx by setting the `fastcgi_param SCRIPT_FILENAME` to `/var/www/$fastcgi_script_name;` +# Vichan Docker Setup -The default docker compose settings are intended for development and testing purposes. -The folder structure expected by compose is as follows +The `php-fpm` process runs containerized. +The PHP application always uses `/var/www` as its work directory and home folder. If `/var/www` is bind mounted, you must adjust the path passed via FastCGI to `php-fpm`. +To fix this: +1. **Adjust the root path**: Set `fastcgi_param SCRIPT_FILENAME` to `/var/www/$fastcgi_script_name;` in your nginx config. + +The default Docker Compose settings are meant for development and testing. + +Expected folder structure: ``` └── local-instances └── 1 - ├── mysql + ├── db └── www ``` -The vichan container is by itself much less rigid. + +To run the app: +1. **Start all containers**: Run `docker compose up -d --build` at the root of vichan directory +2. **Rebuild just the PHP container**: Run `docker compose up -d --build php` (useful during development) + +--- + +## PHP File Size Limit + +To upload larger files, increase the default PHP file size limit (2MB). Since this setup uses Docker, follow these steps: + +1. **Open the config file**: Edit `./docker/php/php.ini` in your project directory. +2. **Add or update these lines** to increase the file size limit to 10MB: + ```ini + upload_max_filesize = 10M + post_max_size = 10M + ``` +3. **Restart your containers** to apply the changes: + ```bash + docker compose restart + ``` + +--- + +By default, PHP limits file uploads to **2MB** — so increasing this is often required when uploading images or documents. + +--- + +## Using the `.env` File + +Environment variables for the Docker Compose setup can be managed easily using a `.env` file. + +### Steps to Use It: +1. **Copy the example**: Start by copying `.env.example` to `.env` + ```bash + cp .env.example .env + ``` +2. **Edit `.env`**: Please make sure to change the default passwords for your setup. + +### What It Controls: +- Instance folder reference (e.g. `local-instances/0`) +- Database credentials +- Redis connection details +- Secure login +- Optional SSL certificate paths for nginx -Use `docker compose up --build` to start the docker compose. -Use `docker compose up --build -d php` to rebuild just the vichan container while the compose is running. Useful for development. +# Vichan Podman Setup (Docker alternative) + +**Podman** offers a daemonless, rootless alternative for running Vichan in containers. Podman is API-compatible with Docker, allowing you to use the existing `compose.yml` file with minimal changes, while providing a more secure and lightweight environment. + +This tutorial is for administrators who prefer to avoid Docker, addressing security concerns and ensuring a robust Vichan install. + +--- + +## Why Podman? + +- **Daemonless**: Unlike Docker, Podman doesn’t require a central daemon, reducing the attack surface and eliminating the need for a privileged process. +- **Rootless**: Podman runs containers as a non-root user by default, improving security by limiting the impact of potential container escapes. +- **Lightweight**: Podman has a smaller footprint and is better suited for environments where simplicity and security are priorities. +- **Docker Compatibility**: Podman supports Docker Compose files via Podman Compose, making it easy to adapt the existing Vichan setup. + +Learn more at: https://podman.io +--- + +## Prerequisites + +**Install Podman** + +The official installation tutorial can be found at: https://podman.io/docs/installation + +**Configure the `.env` file** as described in the main setup guide (copy `.env.example` to `.env` and update passwords). + +--- + +## Steps to Run Vichan with Podman + +### 1. Prepare File Permissions + +Since Podman runs rootless, ensure the `local-instances/1/db` and `local-instances/1/www` directories are writable by your user: + +```bash +chmod -R u+rw local-instances/1 +``` + +If using SELinux (e.g., on Fedora), you may need to set the correct context: + +```bash +chcon -R -t container_file_t local-instances/1 +``` + +### 2. Start Containers with Podman Compose + +Run the following command from the root of the Vichan project directory to build and start all containers: + +```bash +podman-compose up -d --build +``` + +This command mirrors `docker compose up -d --build` but uses Podman’s container engine. + +### 3. Rebuild Specific Containers + +To rebuild only the PHP container (e.g., during development): + +```bash +podman-compose up -d --build php +``` + +--- + +## Managing Podman Containers + +**List running containers:** + +```bash +podman ps +``` + +**Stop all containers:** + +```bash +podman-compose down +``` + +**View logs for a specific service (e.g., PHP):** + +```bash +podman logs vichan_php +``` + +## Troubleshooting + +### unqualified-search-registries for Docker.io + +1. Edit the config file with `nano /etc/containers/registries.conf` + +2. Add the registry for `docker.io` with `unqualified-search-registries = ["docker.io"]` + +3. Save and exit + +4. Run `podman-compose up -d` \ No newline at end of file diff --git a/docker/nginx/Dockerfile b/docker/nginx/Dockerfile index d9d4bcc4..6ddce075 100644 --- a/docker/nginx/Dockerfile +++ b/docker/nginx/Dockerfile @@ -1,4 +1,4 @@ -FROM nginx:1.25.3-alpine +FROM nginx:1.27.5-alpine-slim COPY . /code RUN adduser --system www-data \ diff --git a/docker/php/Dockerfile b/docker/php/Dockerfile index 1882bc9d..86c161d1 100644 --- a/docker/php/Dockerfile +++ b/docker/php/Dockerfile @@ -1,7 +1,7 @@ # Based on https://github.com/dead-guru/devichan/blob/master/php-fpm/Dockerfile FROM composer:lts AS composer -FROM php:8.1-fpm-alpine +FROM php:8.3-fpm-alpine RUN apk add --no-cache \ zlib \ @@ -47,7 +47,7 @@ RUN apk add --no-cache \ && pecl install -o -f igbinary \ && pecl install redis \ && pecl install imagick \ - $$ docker-php-ext-enable \ + && docker-php-ext-enable \ igbinary \ redis \ imagick \ diff --git a/docker/php/php.ini b/docker/php/php.ini new file mode 100644 index 00000000..0e4afdc0 --- /dev/null +++ b/docker/php/php.ini @@ -0,0 +1,3 @@ +post_max_size=10M +upload_max_filesize=10M +max_file_uploads=5 \ No newline at end of file diff --git a/inc/Data/Driver/RedisCacheDriver.php b/inc/Data/Driver/RedisCacheDriver.php index 46e602d4..f2c445c1 100644 --- a/inc/Data/Driver/RedisCacheDriver.php +++ b/inc/Data/Driver/RedisCacheDriver.php @@ -1,47 +1,65 @@ inner = new \Redis(); $this->inner->connect($host, $port); + if ($password) { $this->inner->auth($password); } + if (!$this->inner->select($database)) { - throw new \RuntimeException('Unable to connect to Redis!'); + throw new \RuntimeException('Unable to select Redis database ' . $database); } - $$this->prefix = $prefix; + $this->prefix = $prefix; } + // Retrieves a value from the cache by key public function get(string $key): mixed { + $ret = $this->inner->get($this->prefix . $key); if ($ret === false) { + // Return null if the key doesn't exist return null; } + return \json_decode($ret, true); } + // Stores a value in the cache with an optional expiration time public function set(string $key, mixed $value, mixed $expires = false): void { - if ($expires === false) { - $this->inner->set($this->prefix . $key, \json_encode($value)); + // Convert the value to JSON for storage + $encodedValue = \json_encode($value); + + if ($expires === false || !is_numeric($expires) || $expires <= 0) { + // Store the value without an expiration + $this->inner->set($this->prefix . $key, $encodedValue); } else { - $expires = $expires * 1000; // Seconds to milliseconds. - $this->inner->setex($this->prefix . $key, $expires, \json_encode($value)); + // Store the value with an expiration time (in seconds) + $ttl_seconds = (int)$expires; + $this->inner->setex($this->prefix . $key, $ttl_seconds, $encodedValue); } } + // Deletes a specific key from the cache public function delete(string $key): void { + // Remove the key from Redis $this->inner->del($this->prefix . $key); } + // Clears all data in the current Redis database public function flush(): void { $this->inner->flushDB(); } diff --git a/inc/cache.php b/inc/cache.php index 293660fd..6e81039a 100644 --- a/inc/cache.php +++ b/inc/cache.php @@ -12,20 +12,32 @@ defined('TINYBOARD') or exit; class Cache { private static function buildCache(): CacheDriver { global $config; + // Determine if the cache engine is configured via environment variables. + $engine = \getenv('VICHAN_CACHE_ENGINE') ?: $config['cache']['enabled']; - switch ($config['cache']['enabled']) { + switch ($engine) { case 'memcached': return new MemcachedCacheDriver( $config['cache']['prefix'], $config['cache']['memcached'] ); case 'redis': + $host = $config['cache']['redis']["host"] ?? 'localhost'; + $port = $config['cache']['redis']["port"] ?? 6379; + $password = $config['cache']['redis']["password"] ?? ''; + $database = $config['cache']['redis']["database"] ?? 1; + + $host = getenv('VICHAN_CACHE_HOST') ?: $host; + $port = getenv('VICHAN_CACHE_PORT') ?: $port; + $password = getenv('VICHAN_CACHE_PASSWORD') ?: $password; + $database = getenv('VICHAN_CACHE_DATABASE') ?: $database; + return new RedisCacheDriver( $config['cache']['prefix'], - $config['cache']['redis'][0], - $config['cache']['redis'][1], - $config['cache']['redis'][2], - $config['cache']['redis'][3] + $host, + $port, + $password, + $database ); case 'apcu': return new ApcuCacheDriver; diff --git a/inc/config.php b/inc/config.php index 4f917f82..458b9ee1 100644 --- a/inc/config.php +++ b/inc/config.php @@ -146,6 +146,7 @@ */ // Uses a PHP array. MUST NOT be used in multiprocess environments. + // This will be ignored if a environment variable ( VICHAN_CACHE_ENGINE ) is set. $config['cache']['enabled'] = 'php'; // The recommended in-memory method of caching. Requires the extension. Due to how APCu works, this should be // disabled when you run tools from the cli. @@ -161,20 +162,23 @@ // $config['cache']['enabled'] = 'none'; // Timeout for cached objects such as posts and HTML. - $config['cache']['timeout'] = 60 * 60 * 48; // 48 hours - - // Optional prefix if you're running multiple vichan instances on the same machine. - $config['cache']['prefix'] = ''; - - // Memcached servers to use. Read more: http://www.php.net/manual/en/memcached.addservers.php - $config['cache']['memcached'] = array( - array('localhost', 11211) + $config['cache']['redis'] = array( + 'host' => 'localhost', + 'port' => 6379, + 'password' => '', + 'database' => 1 ); - // Redis server to use. Location, port, password, database id. - // Note that vichan may clear the database at times, so you may want to pick a database id just for - // vichan to use. - $config['cache']['redis'] = array('localhost', 6379, '', 1); + // Cache timeout for cached objects + $config['cache']['timeout'] = 60 * 60 * 48; // 48 hours + + // Optional prefix for multiple vichan instances + $config['cache']['prefix'] = ''; + + // Memcached servers (not used) + $config['cache']['memcached'] = [ + ['localhost', 11211] + ]; // EXPERIMENTAL: Should we cache configs? Warning: this changes board behaviour, i'd say, a lot. // If you have any lambdas/includes present in your config, you should move them to instance-functions.php diff --git a/inc/template.php b/inc/template.php index 17df316b..11d9ea10 100644 --- a/inc/template.php +++ b/inc/template.php @@ -142,7 +142,8 @@ class Tinyboard extends Twig\Extension\AbstractExtension new Twig\TwigFunction('ratio', 'twig_ratio_function'), new Twig\TwigFunction('secure_link_confirm', 'twig_secure_link_confirm'), new Twig\TwigFunction('secure_link', 'twig_secure_link'), - new Twig\TwigFunction('link_for', 'link_for') + new Twig\TwigFunction('link_for', 'link_for'), + new Twig\TwigFunction('check_container', 'twig_check_container') ); } @@ -225,3 +226,19 @@ function twig_secure_link_confirm($text, $title, $confirm_message, $href) { function twig_secure_link($href) { return $href . '/' . make_secure_link_token($href); } + +/* + * ==================== + * Container Detection + * =================== + */ + +function twig_check_container() { + static $is_container = null; + if ($is_container === null) { + $is_docker = \is_file("/.dockerenv") || \is_file("/run/.containerenv"); + $is_kubernetes = \is_file("/var/run/secrets/kubernetes.io/serviceaccount/namespace"); + $is_container = $is_docker || $is_kubernetes; + } + return $is_container; +} diff --git a/install.php b/install.php index 6c8d627d..a2f6f3a5 100644 --- a/install.php +++ b/install.php @@ -387,7 +387,7 @@ if (file_exists($config['has_installed'])) { CHANGE `theme` `theme` VARCHAR( 40 ) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL , CHANGE `name` `name` VARCHAR( 40 ) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL , CHANGE `value` `value` TEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL , - DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;") or eror(db_error()); + DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;") or error(db_error()); case 'v0.9.6-dev-10': query("ALTER TABLE `antispam` CHANGE `board` `board` VARCHAR( 58 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;") or error(db_error()); @@ -590,12 +590,12 @@ if (file_exists($config['has_installed'])) { case '4.9.90': case '4.9.91': case '4.9.92': - foreach ($boards as &$board) { - query(sprintf('ALTER TABLE ``posts_%s`` ADD `slug` VARCHAR(255) DEFAULT NULL AFTER `embed`;', $board['uri'])) or error(db_error()); + foreach ($boards as &$board) { + query(sprintf('ALTER TABLE ``posts_%s`` ADD `slug` VARCHAR(255) DEFAULT NULL AFTER `embed`;', $board['uri'])) or error(db_error()); } - case '4.9.93': - query('ALTER TABLE ``mods`` CHANGE `password` `password` VARCHAR(255) NOT NULL;') or error(db_error()); - query('ALTER TABLE ``mods`` CHANGE `salt` `salt` VARCHAR(64) NOT NULL;') or error(db_error()); + case '4.9.93': + query('ALTER TABLE ``mods`` CHANGE `password` `password` VARCHAR(255) NOT NULL;') or error(db_error()); + query('ALTER TABLE ``mods`` CHANGE `salt` `salt` VARCHAR(64) NOT NULL;') or error(db_error()); case '5.0.0': query('ALTER TABLE ``mods`` CHANGE `salt` `version` VARCHAR(64) NOT NULL;') or error(db_error()); case '5.0.1': @@ -611,9 +611,9 @@ if (file_exists($config['has_installed'])) { UNIQUE KEY `u_pages` (`name`,`board`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;') or error(db_error()); case '5.1.1': - foreach ($boards as &$board) { - query(sprintf("ALTER TABLE ``posts_%s`` ADD `cycle` int(1) NOT NULL AFTER `locked`", $board['uri'])) or error(db_error()); - } + foreach ($boards as &$board) { + query(sprintf("ALTER TABLE ``posts_%s`` ADD `cycle` int(1) NOT NULL AFTER `locked`", $board['uri'])) or error(db_error()); + } case '5.1.2': query('CREATE TABLE IF NOT EXISTS ``nntp_references`` ( `board` varchar(60) NOT NULL, @@ -680,7 +680,7 @@ function create_config_from_array(&$instance_config, &$array, $prefix = '') { session_start(); if ($step == 0) { - // Agreeement + // Agreement $page['body'] = '

@@ -914,20 +914,64 @@ if ($step == 0) { 'config' => $config, )); } elseif ($step == 2) { - - // Basic config $page['title'] = 'Configuration'; - $sg = new SaltGen(); - $config['cookies']['salt'] = $sg->generate(); + + // Initialize configuration with defaults and override with environment variables + $config['cookies'] = array( + 'mod' => getenv('VICHAN_COOKIES_MOD') !== false ? getenv('VICHAN_COOKIES_MOD') : 'mod', + 'salt' => $sg->generate(), + ); + + $config['flood_time'] = getenv('VICHAN_FLOOD_TIME') !== false ? (int)getenv('VICHAN_FLOOD_TIME') : 30; + $config['flood_time_ip'] = getenv('VICHAN_FLOOD_TIME_IP') !== false ? (int)getenv('VICHAN_FLOOD_TIME_IP') : 120; + $config['flood_time_same'] = getenv('VICHAN_FLOOD_TIME_SAME') !== false ? (int)getenv('VICHAN_FLOOD_TIME_SAME') : 3600; + $config['max_body'] = getenv('VICHAN_MAX_BODY') !== false ? (int)getenv('VICHAN_MAX_BODY') : 1800; + $config['reply_limit'] = getenv('VICHAN_REPLY_LIMIT') !== false ? (int)getenv('VICHAN_REPLY_LIMIT') : 250; + $config['max_links'] = getenv('VICHAN_MAX_LINKS') !== false ? (int)getenv('VICHAN_MAX_LINKS') : 20; + + $config['max_filesize'] = getenv('VICHAN_IMAGES_MAX_FILESIZE') !== false ? (int)getenv('VICHAN_IMAGES_MAX_FILESIZE') : 10485760; // This is 10MB + $config['thumb_width'] = getenv('VICHAN_IMAGES_THUMB_WIDTH') !== false ? (int)getenv('VICHAN_IMAGES_THUMB_WIDTH') : 250; + $config['thumb_height'] = getenv('VICHAN_IMAGES_THUMB_HEIGHT') !== false ? (int)getenv('VICHAN_IMAGES_THUMB_HEIGHT') : 250; + $config['max_width'] = getenv('VICHAN_IMAGES_MAX_WIDTH') !== false ? (int)getenv('VICHAN_IMAGES_MAX_WIDTH') : 10000; + $config['max_height'] = getenv('VICHAN_IMAGES_MAX_HEIGHT') !== false ? (int)getenv('VICHAN_IMAGES_MAX_HEIGHT') : 10000; + + $config['threads_per_page'] = getenv('VICHAN_DISPLAY_THREADS_PER_PAGE') !== false ? (int)getenv('VICHAN_DISPLAY_THREADS_PER_PAGE') : 10; + $config['max_pages'] = getenv('VICHAN_DISPLAY_MAX_PAGES') !== false ? (int)getenv('VICHAN_DISPLAY_MAX_PAGES') : 11; + $config['threads_preview'] = getenv('VICHAN_DISPLAY_THREADS_PREVIEW') !== false ? (int)getenv('VICHAN_DISPLAY_THREADS_PREVIEW') : 5; + + $config['root'] = getenv('VICHAN_DIRECTORIES_ROOT') !== false ? getenv('VICHAN_DIRECTORIES_ROOT') : '/'; + $config['secure_trip_salt'] = $sg->generate(); $config['secure_password_salt'] = $sg->generate(); + + // Set database configuration from Docker environment variables, leave empty if not found + $config['db'] = array( + 'type' => 'mysql', // Default, required for MySQL + 'server' => getenv('VICHAN_MYSQL_HOST') !== false ? getenv('VICHAN_MYSQL_HOST') : '', + 'database' => getenv('VICHAN_MYSQL_NAME') !== false ? getenv('VICHAN_MYSQL_NAME') : '', + 'user' => getenv('VICHAN_MYSQL_USER') !== false ? getenv('VICHAN_MYSQL_USER') : '', + 'password' => getenv('VICHAN_MYSQL_PASSWORD') !== false ? getenv('VICHAN_MYSQL_PASSWORD') : '', + ); + + // Append secure_login_only to $_SESSION['more'] if VICHAN_SECURE_LOGIN_ONLY is set + if (getenv('VICHAN_SECURE_LOGIN_ONLY') !== false) { + $secure_login_only = (int)getenv('VICHAN_SECURE_LOGIN_ONLY'); + $_SESSION['more'] .= "\n\$config['cookies']['secure_login_only'] = $secure_login_only;"; + } + + // Configuration notice at the top + $page['body'] = '

Configuration Note

' . + '

The following settings can still be configured later. For more customization options, check the Vichan configuration wiki.

'; + + // Append the configuration form + $page['body'] .= Element('installer/config.html', array( + 'config' => $config, + 'more' => $_SESSION['more'], + )); echo Element('page.html', array( - 'body' => Element('installer/config.html', array( - 'config' => $config, - 'more' => $_SESSION['more'], - )), + 'body' => $page['body'], 'title' => 'Configuration', 'config' => $config )); @@ -973,8 +1017,6 @@ if ($step == 0) { echo Element('page.html', $page); } } elseif ($step == 4) { - // SQL installation - buildJavascript(); $sql = @file_get_contents('install.sql') or error("Couldn't load install.sql."); @@ -994,7 +1036,7 @@ if ($step == 0) { $sql_err_count = 0; foreach ($queries as $query) { if ($mysql_version < 50503) - $query = preg_replace('/(CHARSET=|CHARACTER SET )utf8mb4/', '$1utf8', $query); + $query = preg_replace('/(CHARSET=|CHARACTER SET )utf8mb4/', '$1utf8', $query); $query = preg_replace('/^([\w\s]*)`([0-9a-zA-Z$_\x{0080}-\x{FFFF}]+)`/u', '$1``$2``', $query); if (!query($query)) { $sql_err_count++; @@ -1004,10 +1046,22 @@ if ($step == 0) { } $page['title'] = 'Installation complete'; - $page['body'] = '

Thank you for using vichan. Please remember to report any bugs you discover. How do I edit the config files?

'; + $page['body'] = '

Thank you for using vichan. Please report any bugs you discover.

' . + '

If you are new to vichan, please check out the documentation.

'; + + // Admin panel notice + $page['body'] .= '

Next Steps

' . + '

You can now log in to the admin panel at /mod.php using the default credentials:

' . + '

Username: admin

' . + '

Password: password

' . + '

Important: For security, please change the administrator password immediately after logging in.

' . + '

'; + if (!empty($sql_errors)) { - $page['body'] .= '

SQL errors

SQL errors were encountered when trying to install the database. This may be the result of using a database which is already occupied with a vichan installation; if so, you can probably ignore this.

The errors encountered were:

Ignore errors and complete installation.

'; + $page['body'] .= '

SQL errors

SQL errors were encountered when trying to install the database. This may be the result of using a database which is already occupied with a vichan installation; if so, you can probably ignore this.

The errors encountered were:

' . + '

Warning: Ignoring errors is not recommended and may cause installation issues.

' . + '

'; } else { $boards = listBoards(); foreach ($boards as &$_board) { @@ -1024,7 +1078,16 @@ if ($step == 0) { echo Element('page.html', $page); } elseif ($step == 5) { $page['title'] = 'Installation complete'; - $page['body'] = '

Thank you for using vichan. Please remember to report any bugs you discover.

'; + $page['body'] = '

Thank you for using vichan. Please report any bugs you discover.

' . + '

If you are new to vichan, please check out the documentation.

'; + + // Admin panel notice + $page['body'] .= '

Next Steps

' . + '

You can now log in to the admin panel at /mod.php using the default credentials:

' . + '

Username: admin

' . + '

Password: password

' . + '

Important: For security, please change the administrator password immediately after logging in.

' . + '

'; $boards = listBoards(); foreach ($boards as &$_board) { @@ -1038,4 +1101,4 @@ if ($step == 0) { } echo Element('page.html', $page); -} +} \ No newline at end of file diff --git a/templates/footer.html b/templates/footer.html index 2288b013..05ad6645 100644 --- a/templates/footer.html +++ b/templates/footer.html @@ -1,6 +1,8 @@