forked from GithubBackups/vichan
Merge pull request #930 from deffcolony/master
Improved Docker setup, installation, and documentation
This commit is contained in:
commit
de52f98741
60
.env.example
Normal file
60
.env.example
Normal file
@ -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!
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@ -29,6 +29,7 @@
|
||||
thumbs.db
|
||||
Icon?
|
||||
Thumbs.db
|
||||
.env
|
||||
*.patch
|
||||
*.diff
|
||||
*.rej
|
||||
|
||||
94
compose.yml
94
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
|
||||
160
docker/doc.md
160
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:
|
||||
```
|
||||
<vichan-project>
|
||||
└── 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`
|
||||
@ -1,4 +1,4 @@
|
||||
FROM nginx:1.25.3-alpine
|
||||
FROM nginx:1.27.5-alpine-slim
|
||||
|
||||
COPY . /code
|
||||
RUN adduser --system www-data \
|
||||
|
||||
@ -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 \
|
||||
|
||||
3
docker/php/php.ini
Normal file
3
docker/php/php.ini
Normal file
@ -0,0 +1,3 @@
|
||||
post_max_size=10M
|
||||
upload_max_filesize=10M
|
||||
max_file_uploads=5
|
||||
@ -1,47 +1,65 @@
|
||||
<?php
|
||||
namespace Vichan\Data\Driver;
|
||||
|
||||
// Prevent direct access to this file for security
|
||||
defined('TINYBOARD') or exit;
|
||||
|
||||
|
||||
// Handles caching using Redis, a fast in-memory data store
|
||||
class RedisCacheDriver implements CacheDriver {
|
||||
private string $prefix;
|
||||
private \Redis $inner;
|
||||
|
||||
public function __construct(string $prefix, string $host, int $port, ?string $password, string $database) {
|
||||
// Sets up the Redis connection
|
||||
public function __construct(string $prefix, string $host, int $port, ?string $password, int $database) {
|
||||
$this->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();
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
113
install.php
113
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'] = '
|
||||
<textarea style="width:700px;height:370px;margin:auto;display:block;background:white;color:black" disabled>' . htmlentities(file_get_contents('LICENSE.md')) . '</textarea>
|
||||
<p style="text-align:center">
|
||||
@ -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'] = '<div class="ban"><h2>Configuration Note</h2>' .
|
||||
'<p style="text-align:center;">The following settings can still be configured later. For more customization options, <a href="https://github.com/vichan-devel/vichan/wiki/config" target="_blank" rel="noopener noreferrer">check the Vichan configuration wiki.</a></p></div>';
|
||||
|
||||
// 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'] = '<p style="text-align:center">Thank you for using vichan. Please remember to report any bugs you discover. <a href="https://github.com/vichan-devel/vichan/wiki/Configuration-Basics">How do I edit the config files?</a></p>';
|
||||
$page['body'] = '<p style="text-align:center">Thank you for using vichan. <a href="https://github.com/vichan-devel/vichan/issues/new/choose" target="_blank" rel="noopener noreferrer">Please report any bugs you discover.</a></p>' .
|
||||
'<p style="text-align:center">If you are new to vichan, <a href="https://github.com/vichan-devel/vichan/wiki" target="_blank" rel="noopener noreferrer">please check out the documentation.</a></p>';
|
||||
|
||||
// Admin panel notice
|
||||
$page['body'] .= '<div class="ban"><h2>Next Steps</h2>' .
|
||||
'<p>You can now log in to the admin panel at <strong>/mod.php</strong> using the default credentials:</p>' .
|
||||
'<p><strong>Username:</strong> admin</p>' .
|
||||
'<p><strong>Password:</strong> password</p>' .
|
||||
'<p><strong>Important:</strong> For security, please change the administrator password immediately after logging in.</p>' .
|
||||
'<p style="text-align:center"><a href="/mod.php"><button>Go to Admin Panel</button></a></p></div>';
|
||||
|
||||
|
||||
if (!empty($sql_errors)) {
|
||||
$page['body'] .= '<div class="ban"><h2>SQL errors</h2><p>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.</p><p>The errors encountered were:</p><ul>' . $sql_errors . '</ul><p><a href="?step=5">Ignore errors and complete installation.</a></p></div>';
|
||||
$page['body'] .= '<div class="ban"><h2>SQL errors</h2><p>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.</p><p>The errors encountered were:</p><ul>' . $sql_errors . '</ul>' .
|
||||
'<p style="text-align:center;color:#d00"><strong>Warning:</strong> Ignoring errors is not recommended and may cause installation issues.</p>' .
|
||||
'<p style="text-align:center"><a href="?step=5"><button>Next</button></a></p></div>';
|
||||
} 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'] = '<p style="text-align:center">Thank you for using vichan. Please remember to report any bugs you discover.</p>';
|
||||
$page['body'] = '<p style="text-align:center">Thank you for using vichan. Please report any bugs you discover.</p>' .
|
||||
'<p style="text-align:center">If you are new to vichan, <a href="https://github.com/vichan-devel/vichan/wiki">please check out the documentation</a>.</p>';
|
||||
|
||||
// Admin panel notice
|
||||
$page['body'] .= '<div class="ban"><h2>Next Steps</h2>' .
|
||||
'<p>You can now log in to the admin panel at <strong>/mod.php</strong> using the default credentials:</p>' .
|
||||
'<p><strong>Username:</strong> admin</p>' .
|
||||
'<p><strong>Password:</strong> password</p>' .
|
||||
'<p><strong>Important:</strong> For security, please change the administrator password immediately after logging in.</p>' .
|
||||
'<p style="text-align:center"><a href="/mod.php"><button>Go to Admin Panel</button></a></p></div>';
|
||||
|
||||
$boards = listBoards();
|
||||
foreach ($boards as &$_board) {
|
||||
@ -1038,4 +1101,4 @@ if ($step == 0) {
|
||||
}
|
||||
|
||||
echo Element('page.html', $page);
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,8 @@
|
||||
<footer>
|
||||
<p class="unimportant" style="margin-top:20px;text-align:center;">- Tinyboard +
|
||||
<a href="https://github.com/vichan-devel/vichan">vichan</a> {{ config.version }} -
|
||||
<a href="https://github.com/vichan-devel/vichan">vichan</a> {{ config.version }}
|
||||
{% if check_container() %}Running Containerized{% endif %}
|
||||
-
|
||||
<br>Tinyboard Copyright © 2010-2014 Tinyboard Development Group
|
||||
<br><a href="https://github.com/vichan-devel/vichan">vichan</a> Copyright © 2012-2025 vichan-devel</p>
|
||||
{% for footer in config.footer %}<p class="unimportant" style="text-align:center;">{{ footer }}</p>{% endfor %}
|
||||
|
||||
@ -17,10 +17,10 @@
|
||||
<i style="font-size:11pt;color:#090" class="fa fa-check"></i>
|
||||
{% else %}
|
||||
{% if test.required %}
|
||||
{% set errors = errors + 1 %}
|
||||
{% set errors = errors + 1 %}
|
||||
<i style="font-size:11pt;color:#d00" class="fa fa-exclamation"></i>
|
||||
{% else %}
|
||||
{% set warnings = warnings + 1 %}
|
||||
{% set warnings = warnings + 1 %}
|
||||
<i style="font-size:11pt;color:#f80" class="fa fa-warning"></i>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
@ -45,12 +45,13 @@
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% if errors %}
|
||||
<p style="text-align:center"><a href="?step=2">Click here to ignore errors and attempt installing anyway (not recommended).</a></p>
|
||||
<p style="text-align:center;color:#d00"><strong>Warning:</strong> Ignoring these problems is not recommended and may cause installation issues.</p>
|
||||
<p style="text-align:center"><a href="?step=2"><button>Proceed Anyway</button></a></p>
|
||||
{% else %}
|
||||
<p style="text-align:center"><a href="?step=2">Click here to proceed with installation.</a></p>
|
||||
<p style="text-align:center"><a href="?step=2"><button>Next</button></a></p>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<p>There were no errors or warnings. Good!</p>
|
||||
<p style="text-align:center"><a href="?step=2">Clik here to proceed with installation.</a></p>
|
||||
<p style="text-align:center"><a href="?step=2"><button>Next</button></a></p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
@ -14,10 +14,7 @@
|
||||
<input type="text" id="db_user" name="db[user]" value="{{ config.db.user }}">
|
||||
|
||||
<label for="db_pass">Password:</label>
|
||||
<input type="password" id="db_pass" name="db[password]" value="">
|
||||
</fieldset>
|
||||
<p style="text-align:center" class="unimportant">The following is all later configurable. For more options, <a href="http://tinyboard.org/docs/?p=Config">edit your configuration files</a> after installing.</p>
|
||||
<fieldset>
|
||||
<input type="password" id="db_pass" name="db[password]" value="{{ config.db.password }}">
|
||||
<legend>Cookies</legend>
|
||||
<label for="cookies_mod">Moderator cookie:</label>
|
||||
<input type="text" id="cookies_mod" name="cookies[mod]" value="{{ config.cookies.mod }}">
|
||||
@ -51,7 +48,38 @@
|
||||
<legend>Images</legend>
|
||||
<label for="max_filesize">Maximum image filesize (bytes):</label>
|
||||
<input type="text" id="max_filesize" name="max_filesize" value="{{ config.max_filesize }}">
|
||||
|
||||
<div class="expandable">
|
||||
<legend>PHP File Size Limit</legend>
|
||||
<div class="body">
|
||||
<p>Configure the PHP file size limit in the <code>php.ini</code> file. If it doesn't exist, create one.</p>
|
||||
<div class="expandable">
|
||||
<legend>Using Docker</legend>
|
||||
<div class="body">
|
||||
<p>Edit or create <code>./vichan/docker/php/php.ini</code> in the project root.</p>
|
||||
<p>To set the limit to 10MB, add:</p>
|
||||
<pre>
|
||||
upload_max_filesize = 10M
|
||||
post_max_size = 10M
|
||||
</pre>
|
||||
<p>Then restart the containers.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="expandable">
|
||||
<legend>Manual Configuration</legend>
|
||||
<div class="body">
|
||||
<p>Edit or create <code>/usr/local/etc/php/php.ini</code>.</p>
|
||||
<p>To set the limit to 10MB, add:</p>
|
||||
<pre>
|
||||
upload_max_filesize = 10M
|
||||
post_max_size = 10M
|
||||
</pre>
|
||||
<p>Then restart the PHP server.</p>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<p>Default limit is 2MB if not set.</p>
|
||||
</div>
|
||||
</div>
|
||||
<label for="thumb_width">Thumbnail width:</label>
|
||||
<input type="text" id="thumb_width" name="thumb_width" value="{{ config.thumb_width }}">
|
||||
|
||||
@ -99,3 +127,51 @@
|
||||
<input type="submit" value="Complete installation">
|
||||
</p>
|
||||
</form>
|
||||
<script>
|
||||
const expandables = document.querySelectorAll('.expandable');
|
||||
expandables.forEach(expandable => {
|
||||
const arrow = document.createElement('span');
|
||||
arrow.innerHTML = ' ▶'; // Right arrow
|
||||
arrow.style.cursor = 'pointer';
|
||||
arrow.style.marginLeft = '5px';
|
||||
expandable.querySelector('legend').appendChild(arrow);
|
||||
expandable.querySelector('legend').style.cursor = 'pointer';
|
||||
expandable.querySelector('legend').style.fontWeight = 'bold';
|
||||
expandable.querySelector('legend').style.display = 'flex';
|
||||
expandable.querySelector('legend').style.alignItems = 'center';
|
||||
expandable.querySelector('legend').style.justifyContent = 'space-between';
|
||||
|
||||
|
||||
const label = expandable.querySelector('legend');
|
||||
const body = expandable.querySelector('.body');
|
||||
label.addEventListener('click', () => {
|
||||
if (body.style.display === 'none' || body.style.display === '') {
|
||||
body.style.display = 'block';
|
||||
arrow.innerHTML = ' ▼'; // Down arrow
|
||||
} else {
|
||||
body.style.display = 'none';
|
||||
arrow.innerHTML = ' ▶'; // Up arrow
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.expandable {
|
||||
border: 1px solid #ccc;
|
||||
padding: 10px;
|
||||
margin: 10px 0;
|
||||
}
|
||||
.expandable legend {
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
}
|
||||
.expandable fieldset {
|
||||
border: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
.expandable .body {
|
||||
display: none; /* Ensure the body is hidden initially */
|
||||
}
|
||||
</style>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user