Why identity-verified accounts are worth the trouble
If you run Nextcloud for a school, an NGO or a public body in Romania, you already know the weak spot of self-registration: anyone with an e-mail address can create an account. Turning registration off means you spend your week creating users by hand. For many organizations the honest middle ground is nextcloud identity verification: the visitor registers from their own phone, proves who they are with a Romanian identity card or driver's license, and the account is created on the spot.
IDRegister is a Nextcloud plugin that does exactly this. The document is read live with RapidOCR, a selfie is matched against the photo on the card with a small head turn for liveness, and the personal number (CNP) is kept only as a salted hash so one document makes one account. The picture of the document and the selfie are never stored. That last part is what makes it defensible under GDPR: you keep the minimum needed to run the service, not a collection of ID scans.
This tutorial walks through the setup from the point of view of a self-hoster. The full details live in the user guide; here I focus on the decisions that matter for a public-sector or NGO deployment.
Prerequisites
Before you start, make sure you have:
- Nextcloud 30 to 34 and PHP 8.1 or newer, with
imagick(GD works as a fallback). - HTTPS on the instance. Phone browsers only hand out camera access over HTTPS, so this is not optional.
- Python 3.8 or newer (
python3) on the server. The app builds its own environment and downloads its reader and face models (RapidOCR, ONNX Runtime, OpenCV and the InsightFacebuffalo_lmodel pack, about 450 MB) into the Nextcloud data directory. That download needs internet access once. - Optionally
tesseract-ocrwithtesseract-ocr-ronas a fallback reader. Tesseract alone reads photographed cards poorly, so treat it as a backup, not the main path. - A MediaLab Works account with an active license, a lifetime license inside its update window, or the 30-day free trial.
A word on GDPR before any data is collected: decide who is the controller, write down why you collect the name and e-mail, and link your own terms on the settings page. IDRegister keeps the CNP only as a salted hash and drops the images, which keeps your processing minimal, but the organizational paperwork is still yours.
Step 1: Install the app and activate the license
Download the archive idregister-x.y.z.tar.gz from Licenses in your MediaLab Works account, then extract it into apps/ (or custom_apps/) so you get apps/idregister/ owned by the web-server user:
cd /var/www/nextcloud/apps
sudo tar -xzf ~/idregister-x.y.z.tar.gz
sudo chown -R www-data:www-data idregister
sudo -u www-data php occ app:enable idregister
Open Administration settings → IDRegister → License, paste your license key and save. The app binds the key to this instance and shows the license as Active. The check runs once a day; without internet the app keeps working for 7 days after the last successful check. Accounts already created are never affected by a license lapse, they keep signing in with their password, and nothing is deleted.
Step 2: Install the reader
On the same settings page, press Install the reader. A background job builds a Python environment in appdata_<id>/idregister/python and downloads the models. From a terminal the same step is:
sudo -u www-data php occ idregister:install-ocr
If you ever need to start over, add --remove. Do this before opening registration to visitors, otherwise they will see a service that cannot read anything.
Step 3: Open registration
The main switch is off by default. Turn it on. The registration page is /index.php/apps/idregister/, and a link is added to the login page. The interface is available in Romanian and English, which suits a Romanian public body well.
Step 4: Decide the checks
All checks are on by default, and I would keep them that way for a public deployment:
- Express mode: the account is created right away with a random user name and a password shown once.
- Registration only from a phone or a tablet: the phone is the device with a camera in hand; a computer shows a QR code and signs in after the phone finishes.
- Selfie compared with the document and head turn during the selfie: the selfie is compared with the photo using InsightFace models on ONNX Runtime, and the head turn proves a live person.
- Refuse copies and screens: color against black-and-white copies, moiré against screens, and glare that moves when the card is tilted. When the check is unsure, the page asks for a tilt and then sends the registration to an administrator.
- Refuse expired documents and one account per identity card.
The reader recognizes old identity cards, the new electronic card (CEI) and the driver's license. The machine-readable zone, the printed labels and the CNP (validated by its check digit) are combined.
Step 5: Configure accounts and the GDPR-relevant limits
Under Accounts you control what the organization allows:
- An administrator has to approve every new account (off by default). For a school this is often the right setting.
- Accepted documents: identity card, driver's license, or both.
- Minimum age, default groups, quota for new users, maximum number of accounts (0 = no limit).
- Allowed and blocked e-mail domains: useful to keep registrations inside your organization's domain.
- Link to your terms, and A phone number is required (on by default; switch it off to make the phone optional). Phone numbers from any country are accepted.
Set Delete unconfirmed registrations after (hours, default 48). Registrations whose e-mail is never confirmed are removed automatically together with the disabled account. That is a clean data-minimization story to put in your records.
Step 6: What the visitor experiences
The visitor opens the page on the phone, holds the document in the frame and follows the prompts (closer, hold still, tilt), then takes a selfie with a small head turn. The account is created and the visitor is signed in. The name from the document becomes the display name and is locked; the e-mail (verified with a six-digit code and a link) and the phone are added in the profile and fixed once confirmed.
On a computer the page shows a QR code; the visitor scans it, completes the flow on the phone, and the computer signs in.
Step 7: Optional extras
- Sign in with Google: create an OAuth client of type Web application in the Google Cloud console, add the redirect URI shown on the settings page (
https://<your server>/index.php/apps/idregister/google/callback), and paste the client ID and secret. Only theopenid,emailandprofilescopes are needed. Google never creates accounts: it only ties an existing account with the same verified address. - Sign in with your phone: paired Android phones approve a sign-in on any computer after a fingerprint, with a key that never leaves the phone.
- Paid registration with Cashier (version 2.1 or newer of IDRegister): when Cashier is installed, licensed and has visible plans, the page offers "Pay a plan instead of scanning an ID". The visitor confirms an e-mail, pays with Stripe and gets an account marked verified by payment, without a document or selfie. Two switches control it: offer the paid path, and require the identity check only for the free path (on by default).
- Companion Android app: the signed APK is under Account → Licenses, requires Android 8.0 or newer, and is the app used for phone sign-in. It is optional; the web page works in any phone browser.
Tips and troubleshooting
- "No text recognition is installed" in Administration settings → Overview: press Install the reader or run
occ idregister:install-ocr. A warning that documents are read with Tesseract means the same thing. - The camera does not start: check HTTPS and camera permission in the browser. The Android app is the fallback.
- Selfies never match: the face models are missing; reinstall the reader. If a selfie does not fit your use case, the selfie check can be switched off.
- "Phone numbers from this country cannot be used here": the rules delivered with your license can carry an optional list of allowed calling codes. It is empty by default and set only by MediaLab Works on request, so write to us if you need it set or cleared. The same rules add a short list of throw-away e-mail services to your blocked domains.
- The paid path does not appear: Cashier is missing, unlicensed, has no visible plan, Stripe is not connected, or the switch is off.
- Testing the reader:
occ idregister:scan <picture>tries the reader on a picture and stores nothing.occ idregister:cleanupdrops registrations that were never confirmed.
Conclusion
For a Romanian school, NGO or public body, IDRegister gives you self-registration without giving up on identity. The visitor needs only a phone and a document they already carry, you get one account per person, and the data you keep is deliberately small: a name, a verified e-mail and phone, and a salted hash of the CNP. The pictures are read in memory and dropped, which is the kind of design you can explain to a DPO without wincing. Start with the product page, follow the guide for the settings, and check the changelog before upgrades. If something is unclear, the knowledge base and FAQ are good next stops, and you can always contact us.