Deployment
This guide covers building and deploying LAMISPlus 3.0 to a production server.
Build
The monorepo uses Maven to build both backend and all frontend plugin bundles in a single command:
cd Lamisplus3.0
mvn clean package -DskipTests
This produces:
api/lamisplus-core/target/lamisplus-core-*.jar, the runnable Spring Boot JAR- Frontend plugin assets embedded inside each plugin JAR under
src/main/resources/static/
Environment Variables
Set these before starting the application:
| Variable | Required | Description |
|---|---|---|
DB_USERNAME | Yes | PostgreSQL username |
DB_PASSWORD | Yes | PostgreSQL password |
JWT_SECRET | Yes | 256-bit base64-encoded secret for JWT signing |
SERVER_PORT | No | HTTP port (default: 8789) |
PLUGIN_STORAGE_PATH | Yes | Path where plugin JARs are persisted |
CORS_ALLOWED_ORIGINS | Yes | Allowed frontend origins (e.g. https://app.hospital.org) |
PLUGIN_STORAGE_PATHis critical. Plugin JARs must be stored outside the Maven build output directory. If you point this totarget/,mvn cleanwill delete all installed plugins and they must be re-uploaded. Use a stable path such as/opt/lamisplus/plugins.
Running the Backend
Direct JAR
java \
-Dspring.profiles.active=prod \
-Dplugins.storage.path=/opt/lamisplus/plugins \
-Xmx2g \
-jar api/lamisplus-core/target/lamisplus-core-*.jar
systemd Service
Create /etc/systemd/system/lamisplus.service:
[Unit]
Description=LAMISPlus 3.0
After=network.target postgresql.service
[Service]
User=lamisplus
WorkingDirectory=/opt/lamisplus
EnvironmentFile=/opt/lamisplus/.env
ExecStart=/usr/bin/java \
-Dspring.profiles.active=prod \
-Dplugins.storage.path=/opt/lamisplus/plugins \
-Xmx2g \
-jar /opt/lamisplus/lamisplus-core.jar
Restart=on-failure
RestartSec=10
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
sudo systemctl enable lamisplus
sudo systemctl start lamisplus
sudo journalctl -u lamisplus -f # follow logs
nginx Reverse Proxy
Route all API and plugin asset requests through nginx:
server {
listen 443 ssl;
server_name app.hospital.org;
# Frontend SPA
root /opt/lamisplus/frontend;
index index.html;
# All API and plugin routes go to Spring Boot
location /api/ {
proxy_pass http://localhost:8789;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Plugin remoteEntry.js and assets served by Spring Boot
location /plugins/ {
proxy_pass http://localhost:8789;
proxy_set_header Host $host;
}
# SPA fallback
location / {
try_files $uri $uri/ /index.html;
}
}
Frontend Build
The frontend is built as part of mvn clean package (the Maven frontend plugin runs pnpm build). The Core SPA output is embedded in the JAR and served at the root.
If you need to build the frontend independently:
cd ui
pnpm build # builds all apps
Copy core/dist/ to your static file server root. Plugin assets are served by the Spring Boot backend from /plugins/{pluginId}/.
Plugin Management
Installing a Plugin
curl -X POST https://app.hospital.org/api/v1/core/plugin/admin/install \
-H "Authorization: Bearer YOUR_SUPER_ADMIN_TOKEN" \
-H "X-Tenant-Id: _system_" \
-F "file=@/path/to/plugin.jar"
Enabling a Plugin for a Tenant
curl -X POST https://app.hospital.org/api/v1/core/plugin/{pluginId}/enable \
-H "Authorization: Bearer YOUR_ADMIN_TOKEN" \
-H "X-Tenant-Id: YOUR_TENANT_ID"
Plugin Storage Location
Installed JARs are stored in PLUGIN_STORAGE_PATH. On restart, the application automatically reloads all JARs from this directory. Ensure this directory is:
- Readable and writable by the
lamisplusservice user - Backed up separately from the application JAR
- Not inside the Maven
target/directory
Database
First-Time Setup
Liquibase runs migrations automatically on startup. No manual schema creation is needed beyond creating the database:
CREATE DATABASE lamisplus_db;
CREATE USER lamisplus_user WITH ENCRYPTED PASSWORD 'strong_password';
GRANT ALL PRIVILEGES ON DATABASE lamisplus_db TO lamisplus_user;
Backup
pg_dump -U lamisplus_user -d lamisplus_db -Fc -f /backups/lamisplus_$(date +%Y%m%d).dump
Health Check
# Application health
curl https://app.hospital.org/actuator/health
# Plugin status
curl https://app.hospital.org/api/v1/core/health/plugins \
-H "Authorization: Bearer TOKEN" \
-H "X-Tenant-Id: _system_"
Checklist Before Going Live
-
JWT_SECRETis a randomly generated 256-bit key, not a default or guessable value -
DB_PASSWORDis strong and not a default value -
PLUGIN_STORAGE_PATHpoints outside oftarget/ -
spring.profiles.active=prodis set, disables dev security config - Actuator endpoints
heapdump,env,beansare disabled or IP-restricted inapplication-prod.yml -
CORS_ALLOWED_ORIGINSis set to the specific frontend domain, not* - TLS/HTTPS configured on nginx
- Database backups scheduled
- Log rotation configured