SVPortal — Quick Start
This is the short version: the handful of things you must do by hand before the portal will let anyone sign in. Once you can log in as an Administrator, everything else — grid name, ROBUST connection, RemoteAdmin, email, feature switches, themes and so on — is configured from the Setup pages inside the portal, not by editing files. For the long version (optional features, cron, OAR backups, TinyMCE, troubleshooting) see Install.md.
If you opened the portal in a browser and were shown “This portal isn’t ready yet”, you are in the right place. That page appears whenever one of the steps below is incomplete. It deliberately doesn’t say which one (it is shown to anyone who visits). The exact reason is written to the PHP error log, on a line beginning SVPortal preflight: — see Finding out what is missing.
1. Prerequisites
You need, before touching SVPortal itself:
- A working OpenSimulator grid with ROBUST running, and its MariaDB database.
- A web server — these notes assume Nginx with PHP-FPM (Apache: see Appendix A of
Install.md). - PHP 8.3 or 8.4, with these extensions:
bash
sudo apt install php8.4-mysql php8.4-mbstring php8.4-curl php8.4-imagick php8.4-fileinfo php8.4-xml
(Adjust 8.4 to your PHP version.) php -m lists what is installed.
No Composer and no other packages are needed — PHPMailer is bundled.
2. Web server serves the portal
Point your web server’s document root at the portal’s public/ directory, and pass .php files to PHP-FPM. A minimal Nginx example:
nginx
server {
listen 443 ssl;
server_name portal.yourgrid.example;
root /var/www/svportal/public;
index index.php;
# TLS certificate lines — see step 3
location = /config.php {
deny all;
return 404;
}
location ~ \.php$ {
fastcgi_pass unix:/run/php/php8.4-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
Adjust the paths, server_name and PHP-FPM socket to match your system. The location = /config.php block stops anyone downloading your configuration file and must come before the .php block. Install.md covers further hardening. Using Apache instead? It isn’t a fully supported setup — see Appendix A of Install.md.
Only the public/ directory is served. The cron/ and OARs/ directories sit outside it, alongside public/.
3. TLS certificate
The portal requires HTTPS and will not work over plain HTTP — its session cookie is marked Secure, so browsers refuse to send it back over HTTP and you get stuck in a login loop.
Get a certificate for the portal’s address, for example with Let’s Encrypt:
bash
sudo certbot --nginx -d portal.yourgrid.example
On a LAN-only test machine a self-signed certificate is enough (your browser will warn; accept it).
4. Create config.php
The release ships config-sample.php. Copy it (inside public/) and edit the copy:
bash
cd /var/www/svportal/public
cp config-sample.php config.php
Only two things need setting at this stage:
| Setting | What to put |
|---|---|
PORTAL_BASE_URL | The portal’s public address, https://, no trailing slash. |
DB_HOST, DB_PORT, DB_NAME, DB_USER, DB_PASS | How the portal connects to your grid’s MariaDB database. |
Leave the rest of config.php alone for now. (It can’t be moved into Setup: the database details are needed to open the database in the first place, and a wrong PORTAL_BASE_URL gets baked into emails the portal has already sent.)
config.php holds your database password, so lock it down:
bash
sudo chown root:www-data config.php
sudo chmod 640 config.php
www-data is the web server user on Debian/Ubuntu — use yours if different. The web server user must be able to read the file; if it can’t, you will see the “not ready” page.
Upgrading an older portal that already has a full
config.php? Don’t do this step. Runphp importsettings.phponce from the command line instead — see the upgrade section ofInstall.md.
5. Database: import the schema, create the user, grant access
Everything here is run on the MariaDB server. The portal’s own tables all start with portal_ and live in the same database as your OpenSim tables.
a) Import the portal schema (take a backup first if this is a live grid database):
bash
mysqldump -u root -p your_database > your_database_backup_$(date +%Y%m%d).sql
mysql -u root -p your_database < portal_schema.sql
b) Create the portal’s database user and grant it the minimum it needs. Substitute your real database name, user name and password — the same ones you put in config.php:
sql
CREATE USER 'webportal'@'localhost' IDENTIFIED BY 'your_password';
-- Read access to everything, including the OpenSim tables.
GRANT SELECT ON your_database.* TO 'webportal'@'localhost';
-- Write access ONLY to the portal's own tables.
GRANT INSERT, UPDATE, DELETE ON your_database.portal_prefs TO 'webportal'@'localhost';
GRANT INSERT, UPDATE, DELETE ON your_database.portal_notifications TO 'webportal'@'localhost';
GRANT INSERT, UPDATE, DELETE ON your_database.portal_news TO 'webportal'@'localhost';
GRANT INSERT, UPDATE, DELETE ON your_database.portal_events TO 'webportal'@'localhost';
GRANT INSERT, UPDATE, DELETE ON your_database.portal_pages TO 'webportal'@'localhost';
GRANT INSERT, UPDATE, DELETE ON your_database.portal_links TO 'webportal'@'localhost';
GRANT INSERT, UPDATE, DELETE ON your_database.portal_log TO 'webportal'@'localhost';
GRANT INSERT, UPDATE, DELETE ON your_database.portal_email_tokens TO 'webportal'@'localhost';
GRANT INSERT, UPDATE, DELETE ON your_database.portal_pending_registrations TO 'webportal'@'localhost';
GRANT INSERT, UPDATE, DELETE ON your_database.portal_restart_queue TO 'webportal'@'localhost';
GRANT INSERT, UPDATE, DELETE ON your_database.portal_oar_backups TO 'webportal'@'localhost';
GRANT INSERT, UPDATE, DELETE ON your_database.portal_oar_uploads TO 'webportal'@'localhost';
GRANT INSERT, UPDATE, DELETE ON your_database.portal_requests TO 'webportal'@'localhost';
GRANT INSERT, UPDATE, DELETE ON your_database.portal_oar_restore_queue TO 'webportal'@'localhost';
GRANT SELECT, INSERT, UPDATE ON your_database.portal_inworld_relay TO 'webportal'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON your_database.portal_sessions TO 'webportal'@'localhost';
GRANT SELECT, INSERT, UPDATE ON your_database.portal_settings TO 'webportal'@'localhost';
GRANT INSERT, UPDATE ON your_database.portal_region_info TO 'webportal'@'localhost';
FLUSH PRIVILEGES;
Two details that commonly cause trouble:
- The host part matters. In MariaDB,
'webportal'@'localhost'and'webportal'@'%'are two completely different accounts. Create the user, and grant, with the same host part. Use'localhost'if the web server and database are on the same machine; otherwise the web server’s address or'%'. portal_sessionsandportal_settingsare the two that cannot be skipped. Without them nobody can sign in at all. A missing grant on any otherportal_table only breaks the one feature that table belongs to — Setup’s Database tab will tell you which, once you’re logged in.
The portal never writes to the OpenSim tables unless you later switch on one of the optional write features in Setup. Those need extra grants, which Setup shows you at that point.
6. Sign in
Reload the portal in your browser. You should now see the normal sign-in page.
Sign in with an in-world account that has the Administrator user level (250 by default — set by USERLEVEL_LABELS in config.php). If you don’t have one yet, set it from the ROBUST console:
set user level First Last 250
Then open Setup and work through its tabs. The Database tab should show “Database OK”. From here on you’re done with files and SQL, apart from anything involving your OpenSim installation or folders on disk, which Setup walks you through as you reach it.
Finding out what is missing
If you’re still seeing “This portal isn’t ready yet”, look in the PHP error log (for PHP-FPM on Debian/Ubuntu that is usually /var/log/php8.4-fpm.log, and/or your Nginx error.log) for the most recent line containing SVPortal preflight:. It names the problem:
| The log says… | What to do |
|---|---|
config.php was not found | Step 4 — cp config-sample.php config.php (inside public/). |
config.php exists … cannot read it | Step 4 — fix owner/group/mode so the web server user can read it. |
config.php could not be loaded | A syntax error from hand-editing. The message after it gives the problem. Check quotes and semicolons. |
does not define … / still has the sample value … | Step 4 — a setting is missing or still holds its placeholder. |
could not connect to the database | Wrong DB_HOST, DB_PORT, DB_NAME, DB_USER or DB_PASS, or the database user doesn’t exist or has no access to that database. The exact MySQL error is on the line just above. |
SELECT on the OpenSim table UserAccounts | Step 5b — the GRANT SELECT ON your_database.* line is missing, or was granted to a different host part. |
… on portal_sessions or … portal_settings (a SELECT failure) | Step 5a — portal_schema.sql hasn’t been imported into this database. |
INSERT/UPDATE/DELETE on portal_sessions or portal_settings | Step 5b — that table’s grant line is missing or incomplete. |
Grants take effect immediately — no restart of Nginx, PHP-FPM or the portal is needed. Reload the page after fixing each item; it will move on to the next problem, if there is one, until the sign-in page appears.
