Self-hosted platform for Zotero
ZotPrime2 is a fully packaged repository aimed to make self-hosted Zotero deployment easier with the last versions of both Zotero client and server. This is the result of sleepless nights spent to deploy Zotero within my organization on a disconnected network.
Feel free to open issues or pull requests if you did not manage to use it.
- x86_64 (amd64)
- ARM64 (aarch64)
- Docker Installation
- GKE Installation
- MicroK8s Installation
- Manage Users and Groups
- Client Build
- Credits
You may install ZotPrime server in:
- Baremetal - Use the IP address of your network interface connected to LAN
- Virtual Machine - Use either:
- IP address of your hypervisor's/VMM's virtual network interface connected to host
- IP address of your host's network interface connected to LAN (requires port forwarding for all endpoints listed below)
- Same PC as Client - Use
127.0.0.1(localhost)
Note: This IP address will be referred to as <SERVER_IP> throughout this guide.
Install Prerequisites:
Install latest Docker Compose plugin:
sudo apt update
sudo apt install docker-compose-pluginInstall required tools for secret generation:
sudo apt install openssl php-climkdir /path/to/your/app && cd /path/to/your/app
git clone --recursive https://github.com/uniuuu/zotprime.git
cd zotprime./bin/install.shConfigure: When prompted, input the IP address of the server from Identify Your Server IP Address.
The system will automatically initialize databases and services on first startup.
| Service | URL |
|---|---|
| Zotero API | http://<SERVER_IP>:8080/ |
| S3 | http://<SERVER_IP>:9000/ |
| PHPMyAdmin | http://<SERVER_IP>:8083/ |
| S3 Web UI | http://<SERVER_IP>:9001/ |
| Stream Server | ws://<SERVER_IP>:8081/ |
All credentials are configured in the .env file:
- Zotero API:
ADMIN_USERNAME/ADMIN_PASSWORD - S3 Web UI:
MINIOROOTUSER/MINIOROOTPASSWORD - PHPMyAdmin:
root/MARIADB_ROOT_PASSWORD
mkdir /path/to/your/app && cd /path/to/your/app
git clone https://github.com/uniuuu/zotprime.git
cd zotprimegcloud init
gcloud iam service-accounts create zotprimeprod
gcloud projects list
gcloud projects add-iam-policy-binding <PROJECT_ID> \
--member="serviceAccount:NAME@PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/owner"Note:
<PROJECT_ID>- Your GCP project IDNAME@PROJECT_ID.iam.gserviceaccount.com- Service account email
cd ./zotprime-k8s/GKE/terraform
gcloud iam service-accounts keys create cred.json \
--iam-account=NAME@PROJECT_ID.iam.gserviceaccount.com
mv cred.json ./auth/
gcloud services enable container.googleapis.com
gcloud services enable cloudresourcemanager.googleapis.com
cp terraform.tfvars_example terraform.tfvarsEdit terraform.tfvars and configure:
project_idregionzonesnode-locationsminnodemaxnodedisksizemachine
terraform init
terraform fmt && terraform validate && terraform plan
terraform apply
gcloud container clusters get-credentials zotprime-k8s-prod
cd ..Check cluster status:
kubectl config get-contexts
kubectl get all --all-namespacesEdit ./helm-chart/values.yaml and update hostnames:
dsuri: http://api-any.yourhostname.io/
s3Pointuri: s3-any.yourhostname.io
api: api-any.yourhostname.io
streamserver: stream-any.yourhostname.io
minios3Data: s3-any.yourhostname.io
phpmyadmin: phpmyadmin-any.yourhostname.io
minios3Web: minioweb-any.yourhostname.ioDeploy:
kubectl create namespace zotprime
helm install zotprime-k8s helm-chart --namespace zotprime
kubectl get -A cm,secrets,deploy,rs,sts,pod,pvc,svc,ingWait for GCP to provision IPs:
kubectl get -A ingCheck the ADDRESS column and setup A records in your DNS hosting.
| Service | URL |
|---|---|
| Zotero API | http://yoursub1.yourdomain.tld |
| S3 | http://yoursub2.yourdomain.tld |
| Stream Server | ws://yoursub5.yourdomain.tld |
| Web Admin | http://yoursub6.yourdomain.tld |
| Web Portal | http://yoursub7.yourdomain.tld |
Admin Services (VPN-only):
- PHPMyAdmin:
http://10.7.7.10 - MinIO Web UI:
http://10.7.7.11
Credentials are configured in the .env file:
- Zotero API:
ADMIN_USERNAME/ADMIN_PASSWORD - S3 Web UI:
MINIOROOTUSER/MINIOROOTPASSWORD - PHPMyAdmin:
root/MARIADB_ROOT_PASSWORD
mkdir /path/to/your/app && cd /path/to/your/app
git clone https://github.com/uniuuu/zotprime.git- MicroK8s
- Kubectl
- Helm
- Docker Engine - Install Docker CE with BuildKit and Compose plugins from Docker's official repository
Enable required addons:
microk8s enable hostpath-storage
microk8s enable helm
microk8s enable registry
microk8s enable dns
microk8s enable ingressEnable MetalLB with your LAN IP range (guide):
microk8s enable metallb:<IP_RANGE>kubectl config get-contexts
kubectl get all --all-namespacescd zotprime/microk8s/scripts
./buildimages.sh
./pushimages.shcd ../
kubectl create namespace zotprime
helm install zotprime-k8s helm-chart --namespace zotprime
kubectl get -A cm,secrets,deploy,rs,sts,pod,pvc,svc,ingGet Ingress IPs:
kubectl get -A ingSetup A records in DNS servers or add entries to /etc/hosts on client and server machines.
| Service | URL |
|---|---|
| Zotero API | http://api.zotprime |
| S3 | http://s3min.zotprime |
| PHPMyAdmin | http://pm.zotprime |
| S3 Web UI | http://min.zotprime |
| Stream Server | ws://stream.zotprime |
| Service | Login | Password |
|---|---|---|
| Zotero API | admin |
admin |
| S3 Web UI | zotero |
zoterodocker |
| PHPMyAdmin | root |
zotero |
The admin.sh script provides a unified interface for managing users and groups.
./bin/admin.sh docker user create <username> <email> <password>Example:
./bin/admin.sh docker user create alice alice@example.com password123./bin/admin.sh docker user listOutput shows userID, username, email, and status (enabled/disabled).
./bin/admin.sh docker user quota <user_id>./bin/admin.sh docker user set-quota <user_id> <quota_mb>./bin/admin.sh docker user disable <username>./bin/admin.sh docker user enable <username>./bin/admin.sh docker group create <owner_id> <name> <type>Group types:
PublicOpen- Anyone can join, no file attachmentsPublicClosed- Visible to all, requires approval to joinPrivate- Invitation-only, not publicly visible
Example:
./bin/admin.sh docker group create 1 "Research Team" Private./bin/admin.sh docker group listShows all groups with ID, name, type, owner, and member count.
./bin/admin.sh docker group delete <group_id>./bin/admin.sh docker group add-user <group_id> <user_id> [role]Roles: member (default) or admin
Example:
./bin/admin.sh docker group add-user 1 2 member
./bin/admin.sh docker group add-user 1 3 admin./bin/admin.sh docker group remove-user <group_id> <user_id>./bin/admin.sh docker group members <group_id>For Kubernetes deployments, replace docker with k8s:
./bin/admin.sh k8s user create alice alice@example.com password123
./bin/admin.sh k8s group listSet MLW argument:
w= Windowsl= Linux
For Docker Installation:
DOCKER_BUILDKIT=1 docker build --progress=plain --file client.Dockerfile \
--build-arg HOST_DS=http://<SERVER_IP>:8080/ \
--build-arg HOST_ST=ws://<SERVER_IP>:8081/ \
--build-arg MLW=l --output build .For GKE Installation:
DOCKER_BUILDKIT=1 docker build --progress=plain --file client.Dockerfile \
--build-arg HOST_DS=http://api-any.yourhostname.io/ \
--build-arg HOST_ST=ws://stream-any.yourhostname.io/ \
--build-arg MLW=l --output build .For MicroK8s Installation:
DOCKER_BUILDKIT=1 docker build --progress=plain --file client.Dockerfile \
--build-arg HOST_DS=http://api.zotprime/ \
--build-arg HOST_ST=ws://stream.zotprime/ \
--build-arg MLW=l --output build ../build/staging/Zotero_VERSION/zoteroFor Windows build:
./build/staging/Zotero_VERSION/zotero.exesudo port install git-lfsNote: The -p m flag specifies Mac platform.
git submodule update --init --recursive
cd client
./config.sh
cd zotero-client
npm install
npm run build
app/scripts/dir_build -p m./staging/Zotero_VERSION/zoteroUse credentials from .env file (ADMIN_USERNAME / ADMIN_PASSWORD).
This project builds upon the work of:
