diff --git a/ct/oxicloud.sh b/ct/oxicloud.sh new file mode 100644 index 000000000..1674840e6 --- /dev/null +++ b/ct/oxicloud.sh @@ -0,0 +1,65 @@ +#!/usr/bin/env bash +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func) + +# Copyright (c) 2021-2026 community-scripts ORG +# Author: vhsdream +# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE +# Source: https://github.com/DioCrafts/OxiCloud + +APP="OxiCloud" +var_tags="${var_tags:-files;documents}" +var_cpu="${var_cpu:-2}" +var_ram="${var_ram:-3072}" +var_disk="${var_disk:-20}" +var_os="${var_os:-debian}" +var_version="${var_version:-13}" +var_unprivileged="${var_unprivileged:-1}" + +header_info "$APP" +variables +color +catch_errors + +function update_script() { + header_info + check_container_storage + check_container_resources + + if [[ ! -d /opt/oxicloud ]]; then + msg_error "No ${APP} Installation Found!" + exit + fi + + if check_for_gh_release "OxiCloud" "DioCrafts/OxiCloud"; then + msg_info "Stopping OxiCloud" + $STD systemctl stop oxicloud + msg_ok "Stopped OxiCloud" + + CLEAN_INSTALL=1 fetch_and_deploy_gh_release "OxiCloud" "DioCrafts/OxiCloud" "tarball" "latest" "/opt/oxicloud" + TOOLCHAIN="$(sed -n '/rust:/s/[^:]*://p' /opt/oxicloud/Dockerfile | awk -F- '{print $1}')" + RUST_TOOLCHAIN=$TOOLCHAIN setup_rust + + msg_info "Updating OxiCloud" + cd /opt/oxicloud + export DATABASE_URL="postgres://${PG_DB_USER}:${PG_DB_PASS}@localhost/${PG_DB_NAME}" + $STD cargo build --release + mv target/release/oxicloud /usr/bin/oxicloud && chmod +x /usr/bin/oxicloud + chown -R oxicloud:oxicloud /mnt/oxicloud /opt/oxicloud /etc/oxicloud + msg_ok "Updated OxiCloud" + + msg_info "Starting OxiCloud" + $STD systemctl start oxicloud + msg_ok "Started OxiCloud" + msg_ok "Updated successfully!" + fi + exit +} + +start +build_container +description + +msg_ok "Completed successfully!\n" +echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}" +echo -e "${INFO}${YW} Access it using the following URL:${CL}" +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8086${CL}" diff --git a/frontend/public/json/oxicloud.json b/frontend/public/json/oxicloud.json new file mode 100644 index 000000000..64e6f8827 --- /dev/null +++ b/frontend/public/json/oxicloud.json @@ -0,0 +1,36 @@ +{ + "name": "OxiCloud", + "slug": "oxicloud", + "categories": [ + 11, + 12 + ], + "date_created": "2026-03-11", + "type": "ct", + "updateable": true, + "privileged": false, + "interface_port": 8086, + "documentation": "https://github.com/DioCrafts/OxiCloud/tree/main/doc", + "website": "https://github.com/DioCrafts/OxiCloud", + "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/oxicloud.webp", + "config_path": "/etc/oxicloud/.env", + "description": "Ultra-fast, secure & lightweight self-hosted cloud storage — your files, photos, calendars & contacts, all in one place. Built in Rust.", + "install_methods": [ + { + "type": "default", + "script": "ct/oxicloud.sh", + "resources": { + "cpu": 2, + "ram": 3072, + "hdd": 20, + "os": "Debian", + "version": "13" + } + } + ], + "default_credentials": { + "username": null, + "password": null + }, + "notes": [] +} diff --git a/install/example.env b/install/example.env new file mode 100644 index 000000000..80e10b9e5 --- /dev/null +++ b/install/example.env @@ -0,0 +1,192 @@ +# ============================================================================= +# OxiCloud Environment Configuration +# ============================================================================= +# Copy this file to .env and modify as needed for your deployment. +# cp example.env .env +# +# All variables have sensible defaults. Only override what you need. +# ============================================================================= + +# ----------------------------------------------------------------------------- +# SERVER CONFIGURATION +# ----------------------------------------------------------------------------- + +# Root directory for file storage (default: ./storage) +OXICLOUD_STORAGE_PATH=./storage + +# Path to static files directory (default: ./static) +OXICLOUD_STATIC_PATH=./static + +# Server port (default: 8086) +OXICLOUD_SERVER_PORT=8086 + +# Server bind address (default: 127.0.0.1) +# Use 0.0.0.0 to bind to all interfaces in Docker +OXICLOUD_SERVER_HOST=127.0.0.1 + +# Public base URL for generating share links and external URLs +# If not set, defaults to http://{OXICLOUD_SERVER_HOST}:{OXICLOUD_SERVER_PORT} +# Example: https://cloud.example.com +#OXICLOUD_BASE_URL=https://cloud.example.com + +# ----------------------------------------------------------------------------- +# DATABASE CONFIGURATION +# ----------------------------------------------------------------------------- + +# PostgreSQL connection string +# Format: postgres://USER:PASSWORD@HOST:PORT/DATABASE +# For Docker: use 'postgres' as the hostname (the docker-compose service name) +# For local development: use 'localhost:5432' +OXICLOUD_DB_CONNECTION_STRING=postgres://postgres:postgres@postgres/oxicloud + +# Maximum number of database connections in the pool (default: 20) +#OXICLOUD_DB_MAX_CONNECTIONS=20 + +# Minimum number of database connections to maintain (default: 5) +#OXICLOUD_DB_MIN_CONNECTIONS=5 + +# Maximum connections for the maintenance pool (background/batch tasks). +# This pool is isolated from user requests, preventing background operations +# (verify_integrity, garbage_collect, storage recalculation) from starving +# interactive traffic. Default: 5 +#OXICLOUD_DB_MAINTENANCE_MAX_CONNECTIONS=5 + +# Minimum connections for the maintenance pool. Default: 1 +#OXICLOUD_DB_MAINTENANCE_MIN_CONNECTIONS=1 + +# Build-time database URL for SQLx compile-time checks +# Only needed during compilation, not at runtime +DATABASE_URL=postgres://postgres:postgres@localhost:5432/oxicloud + +# ----------------------------------------------------------------------------- +# AUTHENTICATION CONFIGURATION +# ----------------------------------------------------------------------------- + +# JWT secret key for signing authentication tokens +# If not set, a secure secret is auto-generated and persisted to +# /.jwt_secret so tokens survive container restarts. +# You only need to set this if you want to share the same secret +# across multiple OxiCloud instances or control it externally. +# Generate a custom secret with: openssl rand -hex 32 +#OXICLOUD_JWT_SECRET= + +# Access token lifetime in seconds (default: 3600 = 1 hour) +#OXICLOUD_ACCESS_TOKEN_EXPIRY_SECS=3600 + +# Refresh token lifetime in seconds (default: 2592000 = 30 days) +#OXICLOUD_REFRESH_TOKEN_EXPIRY_SECS=2592000 + +# ----------------------------------------------------------------------------- +# FEATURE FLAGS +# ----------------------------------------------------------------------------- + +# Enable/disable authentication system (default: true) +#OXICLOUD_ENABLE_AUTH=true + +# Enable per-user storage quotas (default: false) +#OXICLOUD_ENABLE_USER_STORAGE_QUOTAS=false + +# Enable file/folder sharing (default: true) +#OXICLOUD_ENABLE_FILE_SHARING=true + +# Enable trash/recycle bin functionality (default: true) +#OXICLOUD_ENABLE_TRASH=true + +# Enable search functionality (default: true) +#OXICLOUD_ENABLE_SEARCH=true + +# ----------------------------------------------------------------------------- +# OPENID CONNECT (OIDC) / SSO CONFIGURATION +# ----------------------------------------------------------------------------- + +# Enable OIDC authentication (default: false) +OXICLOUD_OIDC_ENABLED=false + +# OIDC provider issuer URL (required if OIDC enabled) +# Example: https://auth.example.com/application/o/oxicloud/ +#OXICLOUD_OIDC_ISSUER_URL= + +# OIDC client ID (required if OIDC enabled) +#OXICLOUD_OIDC_CLIENT_ID= + +# OIDC client secret (required if OIDC enabled) +#OXICLOUD_OIDC_CLIENT_SECRET= + +# Callback URL after OIDC authentication (must match IdP config) +# Default: http://localhost:8086/api/auth/oidc/callback +#OXICLOUD_OIDC_REDIRECT_URI=http://localhost:8086/api/auth/oidc/callback + +# OIDC scopes to request (default: openid profile email) +#OXICLOUD_OIDC_SCOPES=openid profile email + +# Frontend URL to redirect after successful OIDC login +# Default: http://localhost:8086 +#OXICLOUD_OIDC_FRONTEND_URL=http://localhost:8086 + +# Auto-create users on first OIDC login (JIT provisioning) (default: true) +#OXICLOUD_OIDC_AUTO_PROVISION=true + +# Comma-separated list of OIDC groups that grant admin role +# Example: admins,cloud-admins +#OXICLOUD_OIDC_ADMIN_GROUPS= + +# Disable password-based login entirely when OIDC is active (default: false) +#OXICLOUD_OIDC_DISABLE_PASSWORD_LOGIN=false + +# Display name for the OIDC provider shown in UI (default: SSO) +#OXICLOUD_OIDC_PROVIDER_NAME=SSO + +# ----------------------------------------------------------------------------- +# WOPI (WEB APPLICATION OPEN PLATFORM INTERFACE) CONFIGURATION +# ----------------------------------------------------------------------------- + +# Enable WOPI integration for office document editing (default: false) +# Used with Collabora, OnlyOffice, or other WOPI-compatible editors +OXICLOUD_WOPI_ENABLED=false + +# URL to the WOPI client's discovery endpoint +# Example for Collabora: http://collabora:9980/hosting/discovery +# Example for OnlyOffice: http://onlyoffice/hosting/discovery +#OXICLOUD_WOPI_DISCOVERY_URL= + +# Secret key for signing WOPI access tokens +# Falls back to OXICLOUD_JWT_SECRET if not set +#OXICLOUD_WOPI_SECRET= + +# WOPI access token lifetime in seconds (default: 86400 = 24 hours) +#OXICLOUD_WOPI_TOKEN_TTL_SECS=86400 + +# WOPI lock expiration in seconds (default: 1800 = 30 minutes) +#OXICLOUD_WOPI_LOCK_TTL_SECS=1800 + +# ----------------------------------------------------------------------------- +# MEMORY ALLOCATOR TUNING (IMPORTANT FOR RAM USAGE) +# ----------------------------------------------------------------------------- +# OxiCloud uses mimalloc as its global memory allocator for performance. +# By default, mimalloc RETAINS freed memory in internal free-lists instead of +# returning it to the operating system. This causes the process RSS to grow +# over time (e.g., after large file uploads or password hashing) and never +# shrink back — even though the application has already freed that memory. +# +# In containerized / memory-constrained environments (Docker, K8s, VPS with +# limited RAM), this is critical: without these settings, the container can +# appear to "leak" hundreds of MiB that are actually just retained by the +# allocator. +# +# These variables are read directly by the mimalloc C library at startup. +# They are NOT OxiCloud-specific — they are part of mimalloc's official API. +# Docs: https://microsoft.github.io/mimalloc/environment.html + +# MIMALLOC_PURGE_DELAY: Delay (in ms) before freed memory is returned to the OS. +# 0 = return immediately (RECOMMENDED for Docker / limited RAM) +# -1 = never return (maximum performance, highest RAM usage) +# 10 = mimalloc default (slight delay for reuse optimization) +# Setting this to 0 can reduce idle RAM by 80-120 MiB in typical deployments. +MIMALLOC_PURGE_DELAY=0 + +# MIMALLOC_ALLOW_LARGE_OS_PAGES: Use 2 MiB huge pages for allocations. +# 0 = disabled (RECOMMENDED for Docker — avoids RSS inflation from THP) +# 1 = enabled (better TLB performance on bare-metal servers with plenty of RAM) +# When enabled with Linux Transparent Huge Pages (THP), partially-used 2 MiB +# pages inflate the reported RSS by up to 20-30 MiB. +MIMALLOC_ALLOW_LARGE_OS_PAGES=0 \ No newline at end of file diff --git a/install/oxicloud-install.sh b/install/oxicloud-install.sh new file mode 100644 index 000000000..9635d6133 --- /dev/null +++ b/install/oxicloud-install.sh @@ -0,0 +1,72 @@ +#!/usr/bin/env bash + +# Copyright (c) 2021-2026 community-scripts ORG +# Author: vhsdream +# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE +# Source: https://github.com/DioCrafts/OxiCloud + +source /dev/stdin <<<"$FUNCTIONS_FILE_PATH" +color +verb_ip6 +catch_errors +setting_up_container +network_check +update_os + +msg_info "Installing Dependencies" +$STD apt install -y \ + build-essential +msg_ok "Installed Dependencies" + +PG_VERSION="17" setup_postgresql +PG_DB_NAME="oxicloud" PG_DB_USER="oxicloud" setup_postgresql_db +fetch_and_deploy_gh_release "OxiCloud" "DioCrafts/OxiCloud" "tarball" "latest" "/opt/oxicloud" +TOOLCHAIN="$(sed -n '/rust:/s/[^:]*://p' /opt/oxicloud/Dockerfile | awk -F- '{print $1}')" +RUST_TOOLCHAIN=$TOOLCHAIN setup_rust + +msg_info "Building OxiCloud" +cd /opt/oxicloud +export DATABASE_URL="postgres://${PG_DB_USER}:${PG_DB_PASS}@localhost/${PG_DB_NAME}" +$STD cargo build --release +mv target/release/oxicloud /usr/bin/oxicloud && chmod +x /usr/bin/oxicloud +msg_ok "Built OxiCloud" + +msg_info "Configuring OxiCloud" +mkdir -p {/mnt/oxicloud,/etc/oxicloud/static} +sed -e 's|_STORAGE_PATH=.*|_STORAGE_PATH=/mnt/oxicloud|' \ + -e 's|_STATIC_PATH=.*|_STATIC_PATH=/etc/oxicloud/static|' \ + -e 's/_SERVER_HOST=.*/_SERVER_HOST=0.0.0.0|' \ + -e "s|_STRING=.*|_STRING=${DATABASE_URL}|" \ + -e "s|DATABASE_URL=.*|DATABASE_URL=${DATABASE_URL}|" \ + /opt/oxicloud/example.env >/etc/oxicloud/.env +chmod 600 /etc/oxicloud/.env +$STD useradd -U -s /usr/sbin/nologin -M -d /opt/oxicloud oxicloud +chown -R oxicloud:oxicloud /opt/oxicloud /etc/oxicloud /mnt/oxicloud +msg_ok "Configured OxiCloud" + +msg_info "Creating OxiCloud Service" +cat </etc/systemd/system/oxicloud.service +[Unit] +Description=OxiCloud Service +After=network.target + +[Service] +Type=simple +User=oxicloud +Group=oxicloud +EnvironmentFile=/etc/oxicloud/.env +ExecStart=/usr/bin/oxicloud +Restart=always +RestartSec=5 +StandardOutput=journal +StandardError=journal + +[Install] +WantedBy=multi-user.target +EOF +$STD systemctl enable -q --now oxicloud +msg_ok "Created OxiCloud Service" + +motd_ssh +customize +cleanup_lxc