Documentation · For the administrator
Administrator guide
From the first launch to day-to-day operations. Each procedure tells you where to find it in the engine console and, where relevant, whether you need to be an Owner or an Admin.
01 /Requirements
- Windows 10 or Windows 11, 64 bit, or Windows Server 2019 or 2022. Nothing else to install: no database, no runtime.
- A recent browser (Edge, Chrome or Firefox).
- Port 8080 free on this computer (the engine), plus one port for each app (for example 8101, 8102…) and the same port + 1000, used inside the computer.
- A folder where you can write, for example
C:\Pyrite: the engine keeps its data next topyrite.exe. AvoidC:\Program Fileswhen Pyrite starts from the icon (for the Windows service it is the right place: see Pyrite as a Windows service).
02 /First start
- Copy the folder where you want to keep it, then double-click
pyrite.exe. - The engine starts in the background, without a black window: a Pyrite icon (the cubes of the logo) appears in the notification area, near the clock (if you don't see it, open the small arrow ^ next to the clock).
- The first time the program starts from a folder, Windows shows the “Windows Security” window: choose Private networks and allow. If you cancel, or choose only public networks, the other computers of the network can't reach the portal and the apps. Windows asks again for every new folder and for every program file with another name or in another place; a wrong choice is fixed in the Windows firewall settings (“Allow an app through Windows Defender Firewall”), or with
pyrite.exe firewall openas administrator (see The Windows firewall). - The browser opens by itself; on a new engine it shows the first-start page (
http://127.0.0.1:8080/setup/), where you create the first Owner of the engine: the code of the first start (see below), your email, your name (optional) and a password with at least 8 characters, an uppercase and a lowercase letter, a digit and a special character. The Owner is a person of the directory, like everyone else. - When the Owner is created, the engine console opens, already signed in. From then on: console at
http://SERVER-NAME-OR-IP:8080/console/, portal athttp://SERVER-NAME-OR-IP:8080/for whoever uses the apps. Until the first Owner exists, the apps don't start.
If the browser doesn't open, open http://127.0.0.1:8080/setup/ by hand on this computer. If the page can't be opened at all (for example, a server without a browser), create the Owner from a command prompt in the folder: pyrite.exe owner create EMAIL prints a temporary password once; sign in to the console with it and choose a new one (see For technicians).
The code of the first start
The first-start page can be opened from any computer of the network, never from the internet, and only until an Owner exists. To create the Owner it asks for a code that Pyrite prints on the server, so that nobody else in the network can take the engine before you.
- Where the code is: in the window of the engine, and in
logs\engine.log(this is where to read it when Pyrite starts from the icon). With a double click the browser opens with the code already written. - What it looks like: 12 signs in groups of 4, for example
ABCD-EFGH-JKMN, without 0, O, 1, I and L. Uppercase or lowercase, with or without dashes. - Wrong codes: after 5 wrong codes the engine prints a new one, and whoever was wrong waits a minute (then longer). The code changes at most once a minute, and an empty or half-written code doesn't count. If the code changed while you were using it, the page tells you and asks for the new one. If you wait because of too many wrong codes and you are on the server (or come from an SSH tunnel), the page tells you how to go on at once:
pyrite.exe owner create EMAILfrom the server works even with the engine running, or restart the engine. - Only with a name of the engine: the page opens only with an address of the engine (its IP address or the name of the computer). With another name it shows a page that says the right addresses and where the code is.
- Network: in the same page the two network questions are asked (or Skip), see Network rules. When the Windows service is available, the page also asks whether Pyrite starts with your session (icon) or as a service (see Pyrite as a Windows service).
- On a VPS: the page doesn't exist from the internet. Use an SSH tunnel to the port of the engine, or
pyrite.exe owner create EMAIL.
03 /The console and the levels
The console is the engine's management area: apps, people, groups, backups, events. Open http://SERVER:8080/console/: the sign-in page (/console/accesso/) asks for the email and the password of your account in the directory. Only Owners and Admins enter; the old address /_/ leads to the console, so old bookmarks keep working.
If you use Pyrite alone, you are the Owner: the levels below matter only when other people help you manage it.
In the console and in the portal you still find words meant for a company: they are the texts of the program, and for now they stay as they are. “IT” is whoever manages Pyrite; “colleagues” are the other people who use the apps; “the office” is the local network; “Tutta l'azienda” is the starting unit, which you can rename. An Owner can also change the title and the opening texts of the portal (“Company applications”), on the page Portal home page.
- A console session closes by itself after 30 minutes without use (the time is changed in Network rules) and never lasts more than 12 hours from sign-in: see The console closes by itself. After a restart of the engine you sign in again and you are back on the same page.
- If you work in the console on the server, sign out when you have finished and lock the desktop: a console left open is worth the password of whoever signed in.
- The menu with your name has Profile, Change password, the Layout of the console (Engine default, Sidebar on the left, Menu at the top) and Sign out. The layout for whoever hasn't chosen is set by an Owner in Engine settings → Console layout.
- In the menu at the top some items have a short name: Portal (Portal home page), Jobs (Scheduled jobs), History (Engine history), Settings (Engine settings) and Network (Network rules). They are the same pages that the sidebar on the left shows with the full name.
- With the menu at the top, on a narrower screen your name becomes an icon (below 1440 pixels), and below 1280 pixels the menu items go on a second row, which on a phone scrolls sideways.
| level | what they can do |
|---|---|
| Owner | Everything. All the apps (New app, Rescan folders, the Configuration tab, archiving, the approval of uploaded apps), people and groups of every level, the level of each person and the apps each Admin manages, engine settings, portal home page, analytics, backups of everything, the engine's events. At the top, Logs (the engine's log page with the chart) and Advanced: the engine's PocketBase tools inside the console (PocketBase settings: mail, storage, backups, crons, export and import of collections, SQL console with a warning; the registry data only for the collections that no console page manages, if there are any). The last active Owner can't be deleted, disabled or moved to another level. |
| People Admin | The people and the groups of their unit, and the name of their unit at the top. Doesn't see the apps. Sees and manages only the people and groups of that unit; only whoever manages all the units of a person can change that person. Has the History item: who created, renamed, stopped or reactivated the people of the unit, who gave a temporary password, the groups created and the members changed, the password changes and the console sign-ins of those people. Doesn't see the events of the apps, the engine's events, who became Admin of what, the network addresses, nor the events of a person who is also in a unit they don't manage. Doesn't read the name or the email of the Owners (“Owner” is shown instead). An Owner gives the role per unit. |
| App Admin | Their apps, given per unit or per single app: start, stop and restart, backups, data, access. Chooses the groups of the app's unit; gives access to a single person by typing their exact email in the app's Access tab (only people of the app's unit). Doesn't see the people. The App Admin of a whole unit can upload new apps into that unit; the App Admin of a single app can't. An Owner gives the role per unit or per app. |
| Admin (as in 0.7.5) | Only the apps an Owner assigns: start, stop and restart, access and roles, backups, the app's logs, import and the Data tab. Sees the whole directory except the Owners, who appear as “Owner” without an email. Manages the people with the User level: adds them (initial password, to be changed at the first sign-in), changes name and email, gives a temporary password, disables and enables them, gives and removes access to their apps; every change is written in the events. Doesn't delete people and doesn't change levels; sees the other Admins but doesn't change them. Creates groups and changes their members only for the groups that give access only to apps they manage; the other groups are read-only. Can upload apps, which wait for an Owner's approval. |
| User | The portal and the applications they have access to. Doesn't enter the console. |
An Owner gives the roles in the person's card, box Units and roles: People Admin or App Admin per unit, App Admin for a single app, or Owner. The two Admin roles add up on the same person. The roles inside the apps (for example manager or storekeeper) are a different thing: they stay as they were and are set on the app's page, tab Access and roles.
- A role is given only to someone who is in the unit: first add the person to the unit, then give them the role. To take the unit away from them, first remove the role: the engine says which.
- When a person loses their last role (for example because the app they managed was deleted or archived) they become a User and must sign in again. If the app comes back from the archive, the role must be given again from the person's card.
- “Admin” given as a level (for example from the level column of the import) is valid only for those who are in “Tutta l'azienda”. For the people of the other units the roles are given from the person's card.
- Whoever has a role taken away, or an app or a unit changed, is asked to sign in again; whoever gets something more finds it at once.
- If you come from 0.7.5 with a single unit, almost nothing changes. Whoever was an Admin stays an “Admin (as in 0.7.5)” with the same limits, and sees the same things as before. You can take that role away and give the new ones: the Remove the limits button turns a former Admin into a People Admin and, before doing it, shows what they gain and what they lose.
The portal greets whoever has signed in (“Good morning, Anna.”, with the time of their computer and the first word of their name) and shows their apps as tiles, with a band in the color of each app; in the List layout of the home page the apps keep the small colored square. The home page is arranged from the console, in Portal home page.
04 /More customers on one engine: units
A unit is a closed group of people, groups and apps: for example a customer, a team or a site. With units one engine can serve several customers, and each one sees only its own things. At the start, and after the update from 0.7.5, there is one unit, called “Tutta l'azienda” (Italian for “the whole company”; the name is the same in both languages), and everybody is in it: if you don't create others, nothing changes for the people who use Pyrite.
Who sees what
- The Owner sees everything, in every unit.
- The People Admin of a unit sees and manages the people and groups of that unit, and the name of their unit at the top. They don't see the apps. They have the History item with the events about the people of their unit.
- The App Admin sees their apps (start, backup, data, access) and chooses the groups of the app's unit. They don't see the people.
- The User doesn't enter the console: they use the portal, and in the portal they see only the applications of their unit. Before signing in the portal shows only the open-access applications of “Tutta l'azienda”.
- An access is valid only inside a unit: a group opens only the apps of its unit, and a person gets a direct access only to the apps of a unit they belong to. The name of a group is unique inside its unit (two customers can each have their own “Sales”).
- A person can be in more than one unit. Only whoever manages all of their units changes it; for the others the person can be seen but not changed (“protected person”).
What the engine does not show to someone who belongs to another customer
What belongs to another customer “does not exist”: the answer is the same as for a wrong address. The engine decides it, not the page: no answer carries data that the page then hides. This applies to:
- the apps, in the portal and on the home page;
- the name of an app: whoever goes to the address of an app of another customer reads “Application” instead of the name (whoever belongs to the app's customer and has no access reads the name, with the invitation to ask for access; whoever has not signed in reads only the names of the apps of “Tutta l'azienda”);
- the people and groups, the history and the tools;
- whoever manages an app and types a person's email to give them access: if the person is not in the app's unit the answer is always “No person in this unit has this email.”, even if the person exists in another unit;
- whoever types the id of a unit they don't manage: the answer is always “Your level can't do this in the console.”, whether the unit exists or not.
Whoever manages without being an Owner never reads the name or the email of the Owners: the word “Owner” is shown instead. The title, the logo and the extra tiles of the home page stay the same for all customers.
How to create a unit
Units page (Owner only; the item is in the sidebar), New unit, a name. The name of a unit is unique. A unit can be deleted only when it is empty. “Tutta l'azienda” can be renamed but not deleted.
Rename “Tutta l'azienda” when you create the customers' units. It stays the starting unit: the people, groups and apps that nobody has moved are in it, and its name no longer tells the truth. It is also the unit of the apps shown in the portal before sign-in. From the Units page give it a name that says what it really contains.
How to move a person or an app
- A person. In their card, box Units and roles, you switch on the new unit and then switch off the old one. To remove a unit from a person you must first remove it from the groups, the accesses and the roles of that unit: if something is missing the engine says so and changes nothing.
- An app. On the Units page you choose the app and the destination unit. The page first shows what happens (preview) and you confirm. The app takes with it the groups that open only that app; the people who use it get the new unit as well. If an access would be left across two units, Pyrite stops and says what to fix. Whoever is left with nothing in the starting unit must be removed by hand from the person's card.
- Whoever loses an app or a group because of a move, or a role because the unit was deleted, must sign in to the console again.
- Upload app. The app is born in the unit of whoever uploads it. The Owner uploads it into “Tutta l'azienda” and then, if needed, moves it from the Units page. Whoever can upload into more than one unit chooses at the top of the page where the app is born.
- People import. It works in one unit: new people and groups are born there. Whoever imports cannot put themselves in a group (the row is marked as an error, with the reason).
A person always has at least one unit, and a group and an app always have one: if a save (for example from the native card) leaves the field empty, it goes back to “Tutta l'azienda”.
05 /Two-factor authentication
It is a six-digit code, taken from an app on the phone, that you type after email and password. People who enter the console (Owners and Admins) can turn it on. The codes depend on the clock: the time of the server and the time of the phone must be right.
How to turn it on
- From the Profile, from the local network (not from the internet), box Two-factor authentication, Turn on: type your password.
- With a code app on the phone, scan the QR (or type the key by hand).
- Put aside the ten reserve codes (copy, download or print).
- Type the first code and tick I have put them away.
All sessions are closed: you sign in again with password and code. A code that has just been used is no longer valid: wait for the next one, at most 30 seconds.
How to sign in
- In the console: email and password, then the six-digit code from the phone or a reserve code. Each code is valid once.
- In the portal: the code is needed there too. From the local network the portal asks first for email and password and then shows the code field. From the internet the code field is shown to everybody at once, and whoever has no two-factor authentication leaves it empty: this is intended, because showing it only to those who use it would tell from outside who uses it. Opening an app from the portal doesn't ask for another code.
- From the internet the portal always answers “Incorrect email, password or code.”, whatever the error: this is intended.
- Wrong codes: five in 15 minutes stop that person's code for 15 minutes, from any computer, console and portal together. A notice appears in the history (it means that somebody knows their password). The count starts again when the engine restarts.
- Every sign-in with a reserve code leaves a notice in the history with how many are left.
If the phone is lost
- If you have a reserve code: sign in with it and, from the Profile, turn off the two-factor authentication (or make new codes). To make new reserve codes you need the code from the phone: whoever has lost the phone turns it off (a reserve code is valid there) and turns it on again.
- Otherwise an Owner opens the person in the People page and presses Remove two-factor authentication. You can't remove your own from there.
- If the one left out is an Owner and there is no other, from the server:
pyrite.exe owner two-factor-off EMAIL, with the engine running or stopped. It works only for an Owner.
Who can remove it from whom
| who | from whom | how |
|---|---|---|
| the person | themselves | from the Profile, with the password and a code |
| an Owner | another person | People page, Remove two-factor authentication |
| whoever has access to the server | an Owner | command pyrite.exe owner two-factor-off EMAIL |
An Admin who is not an Owner can't remove it from anybody else.
The key and the backups
The codes are protected with a key kept in control\doppia. On Windows the key file opens only on that computer. If the engine is moved to another computer, if Windows is reinstalled or if the key file is lost, whoever had the two-factor authentication is shown as “to be turned on again” and can't enter the console until it is removed: at start the history says who they are. An Owner frees themselves with the command from the server, then removes it from the others on the People page, and each one turns it on again. For this reason the control\doppia folder must be kept together with the rest of the engine data in every copy you make by hand.
With update-restore
The plan of update-restore (see Updating from 0.7.5) says who loses the two-factor authentication by going back, who gets back the one they had, and who is left out because the server's key was made again after the restore point.
06 /People and groups
wherePeople, Groups
In the parts that follow, “an Admin” means the Admin “as in 0.7.5”. The People Admin and the App Admin have narrower limits: what each level can do and see is written in The console and the levels.
Adding a person
Choose New person. For an Owner this opens a PocketBase record. Enter a name, email and initial password that meets the policy (at least one uppercase letter, one lowercase letter, one number, one special character and the minimum length in Engine settings). Then select the level in the same record. For an Admin the engine opens its own page. Enter a name, email and initial password using the same rules, or leave the password blank to generate one that the engine displays only once. The person is created at User level. They sign in to the portal with their email and initial password, then choose a password of their own. A password assigned by the administrator automatically requires a change at first sign-in. You can disable this requirement in the record (“must_change_password”).
Changing a name, email or password
An Owner can make these changes in any person's record. An Admin can edit User-level records. A password set here is temporary and the person must choose a new one at their next sign-in. Anyone can change their own password from the portal under Change password. If the administrator increases the minimum length, people with shorter passwords must replace them at their next sign-in. See Passwords and account recovery for forgotten passwords.
Deactivating a person
Deactivation immediately blocks the person from the portal, console and every app, including sessions currently in use. This is the fastest way to revoke all access when someone leaves. Admins can deactivate and reactivate Users. Only an Owner can delete a person.
Groups
A group brings together people who need the same access, such as a team. Grant access to the group once and it applies to all current and future members. Owners can create and edit all groups. Admins can create groups and change their membership only if the group grants access exclusively to apps they manage. Other groups are read-only for them, but they can grant or revoke any group's access to their own apps.
Importing people, groups and access permissions from Excel
On the People page, Owners and Admins who can create people can select Import from Excel. This opens Import people and groups, where you can load an entire team or company at once.
- Download the template in your language. It has four sheets. Groups contains Name (required) and Description. People contains full name, Email (required, one row per person), Level (User or Admin, blank means User, never Owner, and only an Owner can import Admins), Groups (separated by semicolons, missing groups are created) and Active (yes or no, blank means yes, no creates a disabled account). Access contains Group, App (ID, short name or name) and the optional Role. Instructions is the fourth sheet.
- Upload the file. Excel
.xlsxand legacy.xlsfiles up to 10 MB are supported, with up to 5,000 people and 1,000 groups. A CSV file is treated as a People sheet. - The preview counts new and existing rows and lists errors with their row numbers. Any error blocks the whole import.
- Confirm to start the all-or-nothing import. A progress bar tracks it. The import only adds data. Existing records are unchanged and nobody is removed from a group or deactivated.
- Download the Excel file with the temporary passwords (to be changed at first sign-in) once only, within 10 minutes. The passwords are not stored elsewhere. If you lose the file, reset each person's password in their record. New users do not receive an email. Give them their passwords individually.
An Admin can add only User-level people, assign them to groups they can edit and grant access only to apps they manage. An in-app role belongs to an individual, independently of group access. The engine checks that the Role column names a role defined by the app. Once the import finishes, it assigns the role to new members of the group if the app is running. The results list any roles that could not be assigned because an app was stopped. Assign them from the app's Access and roles tab. Engine history contains a single summary entry without passwords.
Changes an Admin makes to people or groups appear in Engine history under that Admin's name.
07 /Granting and revoking access
wherePeople or Groups → record → App access
Access lets a person enter an app. Grant it directly to a person or to a group to include every member. App access has one switch per app. A person may have both direct access and access through one or more groups. Any single grant lets them in. Apps open to everyone have no grants to manage.
An Owner can grant and revoke access to all apps. Admins can do so only for apps they manage and never for an Owner.
The Access and roles tab on the app page shows who can enter and how. To change access grants, open the person's or group's record.
Revoking access
Revocation takes effect immediately across apps, even for people already signed in. The engine checks the session and access grant on every request.
08 /Roles within apps
whereApp page → Access and roles
A role, such as manager or warehouse clerk, defines what a person can do within a particular app and is managed there. It is independent of their console level and of groups, which determine who can enter.
- The first time someone opens an app from the portal, the engine creates an account in that app with their directory email and name and assigns the app's default role (Configuration tab). After that, the engine leaves the role alone.
- In Access and roles, use the dropdown next to the person to change the role. The role is saved in the app database. An Owner or an Admin who manages the app can change it. Only Owners can change the roles of other Owners. For someone who has never opened the app, the tab shows the role they will receive.
- If the app supports it, users with its highest role can also change other people's roles within the app. Nobody can change their own role.
- App users' email addresses, names and passwords come from the central directory and cannot be changed from within the app.
Below the list, Other users inside the app shows accounts that exist in the app database but lack a central access grant. The engine blocks them at the gateway.
09 /People who already have app accounts
wherePeople → Import from apps (Owners only)
Use this only when apps already have accounts missing from the central directory. For example, an app might have had its own login before moving to the engine. Fresh installations with new apps do not need this step.
- Open People and choose Import from apps.
- The engine reads each app's existing users, adds missing people to the directory and grants them direct access to the apps where they already had accounts. Their existing in-app roles are preserved.
- The initial passwords of newly created people appear below the summary. The console shows them once. Copy them immediately and deliver them in person or through a private channel.
- Review the list and remove test accounts, duplicates and people who no longer use the apps.
10 /What an app can do
The scripts of an app (the pb_hooks and pb_migrations folders) run inside a fence: the engine stops them from doing many things. You don't have to choose anything: this chapter says what to expect.
- Files. An app doesn't read or write files outside its own folder, and writes only in
state\. It doesn't go through links or junctions. A path that starts with a slash is the root of the disk and is refused. - Programs. An app doesn't start programs and doesn't restart itself. It doesn't touch its own server and doesn't restore backups.
- Database. An app doesn't open the databases of other apps. SQL statements that lead outside the database (for example
ATTACH) are refused. - The engine's controls. An app can't remove or skip the engine's controls: the mail of an app always goes, and only, to the declared server, and every send is in the log.
- Network. An app calls only the addresses declared in
app.json. From this version it can't call the engine (console, portal) or another app on the same server, not even by declaring its address: it gets a refusal (403, codeapp_origin) and an event appears: “The app X called the engine from its scripts” or “The app X called the app Y from its scripts” in the console. It can call itself, but the call counts as if it came from a PC of the network, not from the server. It can call another program on this server that is declared inapp.json(for example a local AI model). - Address of the visitor. The apps no longer receive from visitors the addresses written in the headers
CF-Connecting-IP,X-Real-IP,True-Client-IP(and other similar ones): the engine writes them, with the real address. - Who answers on the app's port. The keys the engine uses to talk to an app change at every start of the app. The engine sends nothing to the internal port of an app (app port + 1000) if whoever answers doesn't prove to be the worker that the engine itself started. If another program answers, the app shows as “failed” (didn't start) or “unhealthy” (it was running), with the text “another program is answering on internal port N, not this app”; in the history there is an error event, in the Overview a red notice, and people see “The application isn't responding right now.”. To fix it: see who uses the port (
netstat -ano | findstr :N, the last number is the PID), close that program and press Restart. Even without Restart the app starts again by itself within a few seconds of the port being free.
The limit, stated plainly. The fence greatly reduces what an app's script can do, but it is a defence inside the program: the script runs in the same process as that app's engine, with the same Windows user, and every road has to be closed one by one. Against a script written on purpose to get out, the full guarantee will be to run each app with its own Windows user, which can't touch the files of the others even if it gets out of the fence. This is not in this version; it is planned for a future version. Until then, apps of different customers on the same engine are fine if the scripts are written or checked by whoever runs the engine. Don't upload scripts written by someone you don't trust relying only on the fence.
11 /The icon near the clock
- Left click: a small window opens above the icon, with the engine's status and version, how long it has been on, the apps (running, stopped, failed, with a colored dot), the addresses of the portal and of the console with Copy, the last backup, and the buttons Console, Portal, Logs (the logs folder) and Exit. It closes with a click elsewhere, a second click on the icon or Esc; it works with the keyboard too (Tab, Enter) and follows the light or dark theme of Windows.
- Right click: the menu with Open the console, Open the portal, Open the logs folder, a short status line (how many apps are running), Start with Windows and Exit.
- Double click: opens the console. Double-clicking
pyrite.exeagain while it is running also just opens the console.
12 /Where things are
Everything stays in the folder of pyrite.exe; the engine creates the folders at the first start.
| folder | what is there |
|---|---|
control\pb_data\ | the engine's data: people with their levels, groups, who can enter which app, settings, the list of the apps, the engine's logs and events |
control\pb_data\backups\ | backups of the engine's data (every night at 3:00; the last 7 are kept) and the copies made by earlier versions before an update of the program (pre_migrazione_…zip, to delete by hand; an update makes a restore point in control\aggiornamenti\) |
apps\<app>\ | one folder for each app: app.json (its card), release\ (its code) |
apps\<app>\state\pb_data\ | the app's data (its own database and uploaded files) |
apps\<app>\state\pb_data\backups\ | the app's backups (every night at 3:00 for the apps that are running; the last 7 are kept; manual backups from the app's Backups tab) |
apps\<app>\logs\worker.log | the output of the app's process (also in the console: app page, Status tab) |
logs\engine.log | the engine's messages; up to 10 MB, the 3 previous files are kept |
control\aggiornamenti\ | the restore points of the engine updates (the last 2 are kept) and the copies set aside before going back to a previous version (folders ritorno_…: the engine never deletes them, and the engine's Backups page lists them; delete them by hand when they are no longer needed). They contain personal data (people, password hashes, all the apps' data): when someone's data must be deleted, delete them here too. |
apps\<app>\logs\network.log | the network calls of the app's scripts (address, size, time: never the content); also in the console, app page, Outbound network tab |
archivio\ | apps archived from the console, each with all its data (page Archive: restore them or delete them for good, see The Archive page) |
control\copia_rete.json | how the last copy of the backups to the network folder went (the page and the Overview read it from here; see Copy of the backups to a network folder) |
control\doppia\ | the key that protects the codes of two-factor authentication (see Two-factor authentication) |
control\biglietti\ | the key of the portal sign-in tickets: not to be copied together with the registry backups (see Updating from 0.7.5) |
control\passaggio-ruoli.txt | the summary written at the first start of 0.7.6: who is an Owner, who is an Admin and of which apps |
control\pyrite.json | the network rules of the engine and its identifier (see Network rules) |
control\storico\ | the engine history (storico.db) and, in copie\, its nightly copies; control\storico-fuori.jsonl keeps the events that could not be written there (see The engine history) |
Events are read in the console: Owners see all of them in the Engine history (side bar, see The engine history) and in Logs (at the top); Admins see the events of their apps in the Engine history, on the overview and on the app pages. Each app's page has a Logs tab with the requests that reached the app. To back up everything by hand, stop the engine and copy the whole folder.
13 /Loading and starting an app
Apps arrive as a zip file (for example from an AI agent that follows the agent standard).
- In the console, open Upload app in the side bar and choose (or drag) the zip.
- The engine checks it step by step. Three steps are real checks (the package, the
app.jsoncard, the folder structure); two, “Security check” and “Compatibility with the standard”, are marked demo in this alpha: their score is simulated. Review the app yourself before starting it. In theapp.jsonstep the summary also lists, as information, the tools the app opens to its pages and for whom, and the network addresses it wants to reach: read them before installing. A package with routes under/api/tools/is refused: that path belongs to the engine. The id of an app can't be a name of the engine (console,archivio…) nor the name of a Windows device (con,nul,com1…). Files namedpyrite-archivio.jsonorpyrite-ripristino.jsonnext toapp.jsonare not installed (the summary says so): the engine keeps those names for the Archive. - Read the summary and the delivery notes, then press Install. The app is installed stopped and doesn't appear in the portal yet.
- Uploaded by an Owner: it can be started right away.
- Uploaded by an Admin: it is waiting for approval and the Admin manages it. Until an Owner approves it, nothing starts it and it isn't in the portal. Owners find it in Apps waiting for approval on the overview and on the app's page (who uploaded it and when): they review it and press Approve. To refuse it, an Owner presses Reject (see Apps waiting for approval).
- On the app's page press Start. Then give access to people or groups (People, Groups) and, if the app has roles, set them in the Access and roles tab. Look also at the tabs Tools for pages (what the pages may use, and who; there you also see the Jobs started from the pages, which you can Cancel) and Outbound network (the addresses the app reaches). In a public app that needs users (for example the people who may write), create them in the Data tab (see Sign-up to the apps).
To try, there is an example app, example-parts-pricelist.zip: it is the one of the agent standard, with sign-in and two roles, port 8105.
An Owner can also install an app by copying its folder into apps\ and pressing Rescan folders.
Load app and the port
The port written in app.json is a request. In the summary of Upload app:
- If the apps listen in the network and the Windows firewall says that the port is closed, the summary warns: from the PCs the app will not open.
- If the port is already used, the package is stopped. In both cases Load app offers another free port (one that the firewall lets through, when it can tell) with a button Use port N: one click, and the checks are made again with that port. The chosen port is written in the
app.jsonof the installed app, and the History records the change. It is for new apps. An update never changes the port: the app keeps the one it has, and the summary says so; the port is changed in the Configuration tab. Anapp.jsonwith two keys equal apart from upper and lower case is refused. - If the firewall is off, or Pyrite cannot tell (“not known”), there is no warning.
- Apps already installed: if the app listens in the network and its port is closed by the firewall, its card and the Overview show a warning, with the link to the firewall box and to the Configuration tab. The port of an installed app is changed in its Configuration tab, field Port.
Apps waiting for approval
- When an Admin loads an app, the Owners receive an email (it needs the mail to be set up in the engine; without mail only the Overview warns). The link in the email is always the one of the engine; if the address of the engine is still the default one, the email goes without a link.
- In the card of the app, whoever loaded it sees when the Owners were told (or that there is no mail) and can press Remind the Owners: once every 24 hours, and only with the mail set up.
- An Owner can press Reject and write the reason (from 1 to 300 characters). The app is archived and the History records the reason. Whoever loaded it reads the reason in the Overview for 14 days and in an email, if the mail is set up; both say “an Owner”, not which one (the name stays only in the History). The Admin who loaded it loses the role on that app: to see the notice in the Overview he or she must sign in again.
- If a rejection was left half done (the folder of the app could not be removed, so the archiving is not finished), Approve does not go ahead: the page says to finish or delete that archiving first, from the Archive page.
- An app that is not approved still cannot be started and is not in the portal.
Updating an installed app
A new version of an app arrives as a zip with the same identifier. Start from Upload app, or from Update from zip in the Configuration tab of the app (from there, the zip of another app is refused).
- The engine makes the usual checks and then shows what changes compared with the installed version: versions, fields of
app.json, new migrations. Nothing is touched yet. A migration that has been renamed or removed, and a newapp.jsonthat widens permissions (access that becomes public, new addresses innetwork, newtoolAccessortools, new roles), are a strong warning: read it, and go on only if you are sure. An Owner approves exactly the package seen in the summary: if an Admin uploads another one meanwhile, the page shows the new summary. A package with astatefolder is refused: the data are never replaced. - An Owner presses Update now. An Admin who manages the app sends it for approval: the current version keeps running until an Owner approves or rejects it in the same page.
- All or nothing: the app stops (scheduled jobs in progress are interrupted, as with a restart), a safety copy of
release,app.jsonand the app's data (the wholestatefolder, without temporary files) is made incontrol\aggiornamenti_app\<app>, out of the app's reach, the files are replaced, the new version starts, applies its migrations and must answer. An app that was stopped starts only for this, then stops again. - If something fails, everything goes back by itself as it was, data included (checked with the fingerprints), the previous version restarts and the page says why. If the engine or the PC shuts down halfway, the engine puts back the previous version at its next start, before starting the apps, and writes it in the events.
Afterwards an Owner can press Go back to the previous version in the same tab, typing the app's identifier. The data written after the update are lost for the app: first the state of that moment is copied aside in a da_parte_… folder, which whoever manages Pyrite can read by hand. For each app the engine keeps the copy of the last successful update and the last copy set aside (two folders at most, each as big as the app's data). The port goes back to the one it had before the update, too: if you changed it in the meantime from the Configuration tab, change it again from there after going back; the summary shown before going back says so. They hold personal data: to delete a person's data for good, delete them there too, by hand.
Archiving the app. The safety copies don't go into the archive entry: they move to control\aggiornamenti_app\_archiviate\<entry>, the Archive page shows them with the entry, and they are deleted when you delete the entry. After a restore from the archive, Go back to the previous version isn't offered any more. Copies of an app whose folder is gone are set aside at the engine's start and written in the events at every start, until you remove them.
App stopped after an update. If the previous version couldn't be put back (full disk, a file held by another program, a damaged copy), the app stays stopped with the marker control\aggiornamenti_app\<app>\in_corso.json and the engine tries again at every start. Remove the cause and restart the engine. If that is not enough: with the engine stopped, copy by hand release, app.json and state from file\apps\<app> of the copy named in the marker, then delete in_corso.json. Without the marker the engine doesn't delete that copy any more: it writes it in the events at every start, and you remove it when the app works. update-restore doesn't start while there is a marker: start the engine once first.
14 /Editing an app
whereApp page → Configuration (Owners only)
You can change the name, contact person, description, access mode, version, port, memory limit, roles and default role. The previous manifest is saved alongside the new one as app.json.prima. Changing the port, memory, access or roles automatically restarts the app within a few seconds. Meanwhile its port returns an “updating” message. Editing app.json manually and clicking Rescan folders has the same effect.
Roles work only if the app has a user role field (auth.roleField in the manifest). If it is missing, Configuration shows a notice beneath the roles field.
The same tab lists the checks recommended by PocketBase for production deployment. Rate limiting can be enabled with one click.
To update an app from a zip see Updating an installed app.
Updating app code manually
- Make a manual backup of the app.
- Replace the files inside
apps\<id>\release. Leavestate, which contains the data, untouched. - Restart the app from its page. New migrations run at startup. Then check Status and Logs.
15 /Engine tools
whereTools, or App page → Configuration → Engine tools (Owners only)
Engine tools handle intensive tasks for app scripts without requiring extra programs or libraries. Eight tools are available: Excel and CSV import, Excel and CSV export, PDFs, photos, numbering, change history, statistics and scheduled jobs. Email and notifications, and reservations, are planned.
- Enable a tool for one app at a time using its Configuration switch or the manifest's
toolslist. The setting takes effect immediately without restarting the app. - Enable only the tools listed as required in the app's delivery notes. If a script calls a disabled tool, its error message explains how to enable it.
- The Tools page describes each tool, lists apps that use it and flags manifests that request an unknown tool.
Console imports need no extra tool to be enabled. Every database app has an Import tab.
16 /Importing data from Excel or CSV
whereApp page → Import (Owners and Admins of the app)
- Upload an Excel
.xlsxor legacy Excel 97–2003.xlsfile, a CSV or JSON (.json,.jsonl,.ndjson). The size limit is 100 MB, or 128 MB for JSON. Password-protected files, Excel 95 or earlier formats, damaged files and Word or PowerPoint documents renamed to.xlsare rejected with a message. Reopen them in Excel and save as.xlsx. Excel files can contain at most 5,000,000 distinct strings and 256 MB of text. Beyond that the engine reports “too much text”. Split unusually large files or save as CSV. - Choose the format. For CSV, choose the separator (semicolon by default). For Excel, choose the sheet and layout. In data only, data begins on the first row and columns are named A, B, C and so on. With column titles, the first row supplies the names. With a header section, select the number of initial rows to skip in the preview. The next row supplies the column names and the one after starts the data.
- Check the preview for columns, inferred types, sample rows and warnings.
- Choose the collection and review the engine's proposed column-to-field mappings. A key, such as a registration number, allows the next import to update existing records instead of duplicating them.
- Run a trial. It validates everything without saving. Errors include the row number and reason.
- Import the data. The progress display stays visible until you see the result. Save the settings as a recipe to reuse them for next month's file.
Each import appears in the tab's history with the name of the person who ran it. Undo removes newly created records and restores updated records to their previous values. Both imports and reversals also appear in Engine history.
Field validation still applies (required fields, formats, allowed values). Automatic rules triggered when someone enters a record through the app's pages do not run. Examples include sequential numbers, author, status and capitalization. Supply these values in the file or fix them afterward. Always run a trial first and back up the app before a large import.
Importing an entire file
At the Destination step choose One collection or The whole file, the default even for a single sheet. In The whole file mode the engine examines each sheet (or list in JSON) and suggests:
- the most similar app collection, with a similarity score such as “97% similar”. A green badge requires at least 75% and an unambiguous match. Other matches are marked “review”. Generic names such as “Sheet1” trigger no automatic selection.
- the column-to-field mappings (expand for details) and the key.
- the load order based on collection relationships, such as suppliers before orders, and any related collections that can also be populated from the same sheet. You can turn off a suggestion such as “Also load suppliers from this sheet”. A sheet containing several types of data can be split across its collections.
- What could not be mapped lists hidden sheets, excluded collections and columns with no matching field. A text summary can be passed to the app developer.
The engine selects the key for matching existing records only when unambiguous: a unique index provided by the app, or, in a collection without any single- or multiple-value relationships in the file, a code, registration number or name whose values are all distinct and nonempty. It never chooses a key automatically for a related collection, such as order lines or items in a category. This prevents updates to another order's line. A warning suggests a manual choice, for example “order + item”. Save that key in the recipe so subsequent imports of the same file match and update the records. If a key matches multiple existing records the row is skipped with a reason. The same applies to an ambiguous relationship, such as two orders called “O-1”.
Preview (nothing is saved) shows what each collection would create, update, leave unchanged or skip, including row numbers and an estimate of how many seconds other app writes would wait. Import all becomes available after a successful preview. It is all-or-nothing, in two phases. Validation runs outside a transaction. Writes run in a single transaction limited to 50,000 rows across all sheets and 60 seconds of writes. If a limit is exceeded nothing is saved, and the engine asks you to split the file or import one collection at a time. Any invalid row prevents the import unless you choose Load the good rows anyway.
Stop interrupts a running job. Stopping a multi-collection import leaves nothing saved (“Import stopped: nothing was saved”). For a single collection, batches already saved remain and can be removed with Undo.
Undo in the history reverses the entire import as one operation. It stops without making changes and lists up to 20 affected records if other records reference the imported ones (for example, someone entered an order for an imported supplier). You cannot force that undo. It also stops if records have changed since import. For those changes, Undo anyway is available with confirmation.
The tab also shows the app's policy: “The app allows console imports only into …”. The app developer sets import.consoleCollections in app.json. Without this field, the console can import into every collection like the server, and the tab warns you. Recipes marked “app package” come from the app's release/import folder. You can use them but cannot delete them. Save the recipe lets you repeat the import with one click next month.
A blank cell in a number column leaves the existing number in place and produces a warning. Enter 0 to clear the number. JSON accepts an array of objects, an object containing several arrays (one “sheet” per array), or JSON Lines. Use dot notation for nested values (supplier.name).
“Import preview” for users
Signed-in users can open the “Import preview” tile from the portal home page. Upload a file to preview how the engine will read it using the same format options, without importing any data. The engine stores the file temporarily and deletes it two hours after its last use. This helps users prepare a file before asking the administrator to import it.
17 /The portal home page
wherePortal home (Owners only)
The left side previews the home page as users will see it. Settings are on the right. Choose Save to apply changes to the portal.
- Choose a layout: a tile grid, titled sections (initially created from the apps' owners), or a list.
- Drag tiles to reorder them or move them between sections. Alternatively, select tiles and use Before and After.
- Click a preview element to edit the title and logo, introduction, search, a section or a tile (visibility, color and section).
- Customize colors, background and logo. The editor selects a legible text color automatically and warns about low-contrast choices. The initial palette, tiles included, comes from the Pyrite theme. Your custom colors are kept, and other colors follow the light or dark theme.
- Use Phone and Dark to preview the mobile view and dark theme.
- Discard changes returns to the last saved version. Undo reverses the most recent step. Restore default returns to the original home page.
New apps appear at the end or in Other applications until you arrange them. Hiding a tile changes its visibility on the home page only. The app remains reachable on its port and its access rules still apply.
18 /Sign-up to the apps: decided by whoever manages Pyrite
No app lets people sign up by themselves, not even the public ones: whoever manages Pyrite decides who has a user in an app.
- Apps with sign-in: people enter from the portal with their account of the directory; access is given to people or groups from the console, on the app's page (People, Groups, Access and roles).
- Public apps: anyone in the network opens the pages without signing in. If the app needs users (for example the few people who may write), whoever manages Pyrite creates them in the app's Data tab, one at a time, with the right role if the app uses roles. Every user created, changed or removed there leaves an event with who did it. From that tab nobody can enter the app as one of its users, and it sends no sign-in emails.
- The sign-up page of an app answers “You can't sign up by yourself in this app: its users are decided by IT. Ask whoever manages the app for access.”
- For the users collection of an app with sign-in there is only an information line under Recommended checks: there the users are the copy of the directory, and there is nothing to do.
19 /The Archive page
An Owner archives an app from its page, Configuration tab: the engine stops it, copies its whole folder (code, data, users of the app, backups) into archivio\, checks the copy and only then removes the app from the engine. The Archive page (for the Owners) lists the archived apps: when and by whom, the space used, whether the copy was checked, who could enter back then, the engine version.
- Restore: the app comes back into the engine stopped, as it was, with the same id and port (or new ones, if they are taken now). If you want, it gives back the access of back then (only to the people and groups still in the directory). The outbound network comes back as it was. An app that was waiting for approval comes back waiting. Start it from its page after checking it. The entry stays in the Archive until you delete it.
- Delete for good: deletes the archived copy and frees the space; to confirm, type the id. There is no going back.
- Finish the archiving: if a file of the app was open in another program (File Explorer, an editor, the antivirus), the archiving stops halfway. The copy is made and checked, the app stays in the engine, stopped, and the console doesn't start it. Close that program, then press Finish the archiving on its entry. If the app changed after the copy (for example after going back with
update-restore), the engine deletes nothing: the app stays as it is, and the entry becomes a copy of back then (it can be restored with another id, or deleted). To archive the app, archive it again. - When the engine has an app with the same id as an entry, but not restored from it (for example after going back with
update-restore), the page says so: they are two different copies, and their data can differ. Before deleting one of them for good, check which one to keep.
20 /Backups
whereBackups for all apps, or App page → Backups for one app
- Every night at 3:00 a.m. (computer time), the engine backs up every running database app and keeps the seven most recent automatic backups for each app.
- The same operation backs up the engine registry, including the directory, permissions, events, home page settings and metrics. The engine backup is listed alongside the app backups and can be downloaded. The Backups page restores apps only.
- Take a manual backup whenever needed, such as before updating an app or running a large import. Back up everything now backs up the engine and all apps together (Owners only).
- Admins can view and back up the apps they manage, one at a time. Only Owners can see engine backups.
- Manual backups remain until you delete them.
- Static apps have no database. Copying the app folder is enough to back one up.
Backups live on the same disk as the apps. If that disk fails, the data and backups are lost together. You can enable copying backups to a network folder, such as a NAS. Backups are copied to another disk daily and the Backups page shows the last successful copy. If you do not use network copies, download important backups regularly and keep them elsewhere.
The Engine updates panel on the Backups page lists restore points created when a new pyrite.exe is installed (control\aggiornamenti), and the ritorno_<data> folders that update-restore sets aside before a rollback. They contain personal data and app data written after the update. The engine never deletes them automatically. Remove them manually when no longer needed.
21 /Restoring from backup
whereBackups → Restore on the selected backup
The engine restores the app in four steps:
- It stops the app.
- It copies the current data to
apps\<id>\state\copia_prima_del_ripristino_<data>. - It replaces the data with the contents of the backup.
- It restarts the app if it was running. An app that you stopped with Stop stays stopped until you select Start.
Data returns to the point in time represented by the backup. Anything written afterward exists only in the safety copy.
The engine keeps the three most recent safety copies per app. Configure between 1 and 50 under Engine settings → Backups and restores. It removes older copies only after a successful restore and records each removal in Engine history. The ritorno_ folders created when rolling back the engine are never removed automatically (see above).
22 /Passwords and a forgotten password
- Passwords follow the engine's rules: an uppercase and a lowercase letter, a digit, a special character and the minimum length (8 to start with, set in Engine settings). A password given by someone else (a new person, a temporary password) must be changed at the first sign-in.
- Everyone changes their own password in the portal (Change password); Owners and Admins also in the console, from the menu with their name.
- An Owner who forgot the password: on the console sign-in page, Forgot your password?.
- If the engine can send email (mail settings in Advanced → PocketBase settings, and the Application URL set to the real address of the engine, for example
http://SERVER:8080, notlocalhost; with HTTPS on, the engine writes the link inhttps://by itself), the page sends an email with a link to choose a new password. The link works for 30 minutes, only once. - Otherwise the page shows the command to run on the server, in a command prompt in the folder:
pyrite.exe owner reset EMAIL. It prints a temporary password once; at the next sign-in the console asks for a new one, and the other console sessions of that Owner end.
- If the engine can send email (mail settings in Advanced → PocketBase settings, and the Application URL set to the real address of the engine, for example
- Admins and Users: an Owner gives them a temporary password from the console (for the people with the User level an Admin can do it too); they choose a new one at the first sign-in.
23 /Network rules
The console page Network rules (group System, for Owners only) gathers all the network settings of the engine in one place. Every section saves by itself and says whether the change holds at once or from the next start. If you change nothing, the engine works as in 0.7.4. The settings are kept in control\pyrite.json. pyrite.exe network status shows the rules in use; with the engine stopped, pyrite.exe network reset goes back to the values of 0.7.4 (the file you had stays in control\).
Where the apps listen
Every app has its own port. The port can stay open on the whole network (as in 0.7.4), listen only inside the server (people then reach the app through the engine, with the names) or listen on an address you choose. The change holds at once, without a restart: whoever was using an app finishes what they were doing. Before you save “only inside the machine” the page warns that the other people lose the address name:port. An address that does not exist on the server can't be saved. In the same section you choose the port the new apps start from.
A name for each app
By default the apps are reached with the computer name and a port (http://SERVER:8105/). In The addresses of the apps you can choose one name for each app instead, all under one domain used only for Pyrite, for example app.example.com: the portal is there, and every app has its name under it (booking.app.example.com: the id of the app, or the name chosen in its Exposure tab). Don't write your whole domain (example.com): the single certificate for the apps would be valid for all the sites of that domain (mail, VPN, website).
- One name per app (from the internet); inside name + port: the names are used from the internet, in the local network the addresses stay as they are.
- One name per app, the same names inside too (Same name inside and outside): it needs an internal DNS that knows the names and a certificate valid for all of them. It turns on only if the certificate in use covers all the names, and inside the local network HTTPS is then required.
The entrance from the internet
It is off until you turn it on. The choices are Off, Tunnel (for example Cloudflare), Port open on the router or public address and An existing proxy (nginx, IIS…).
- Tunnel or proxy: the tunnel (for example
cloudflaredon this computer) or the proxy receives the traffic of the internet and passes it to Pyrite. The HTTPS is done by whoever is in front. - Open port: the router sends port 443 to this entrance (or the server has a public address) and Pyrite does the HTTPS. The entrance opens only when the HTTPS of the engine is on (page Certificates): nothing is ever served in clear text over the internet.
- Only the traffic of the internet must arrive there: the router, the tunnel or the proxy must not send it anywhere else. The engine believes the real address of a visitor only when it comes from Who is in front (by default this computer:
127.0.0.1and::1), written in the header you choose (CF-Connecting-IPfor the tunnel,X-Forwarded-Forfor the proxy). If the proxy is on another computer, write its address and choose the address of this computer where the entrance waits. - From the internet people see the portal and only the apps you open to the internet; never the console (see Sign-in).
If the internet arrives where it shouldn't. If the router or a proxy sends by mistake the traffic of the internet to the network entrance, Pyrite says so in the events, in the Overview and in the Network rules page, with the last addresses seen. It only warns and blocks nothing: whoever arrives from there is treated like someone in the local network. Fix the router or the proxy.
Which apps are seen from the internet
Every app has its own choice, Local network only or Internet too, in the Exposure tab of its page. New apps start as “Local network only” (except when the users arrive only from the internet).
- An Owner decides, and can also give the app a name for the internet (empty: the id of the app under the domain of the apps).
- An Admin of the app can take it off the internet on their own (Take off the internet). To open it, the Admin asks (Ask to open it to the internet, with a note if they want): the request appears under To look at and in the Exposure tab, where an Owner can Approve or Refuse. The engine history keeps who asked and who decided. When an Owner approves, the name of the app goes into the public DNS.
- From the internet an app always opens after the sign-in to the portal.
- Address in emails: the links in the emails the apps send (address check, forgotten password) no longer lead to
localhost. The engine writes the right address in the app by itself, at every start and without restarting it; the Exposure tab shows it.
The two questions and the command pyrite.exe network setup
Two questions choose the starting values: Where is the server and how do you get there (From a private network or Only from the internet, for a VPS) and Where do the users come from (From the local network, From the internet or From both, app by app). The answers only choose starting values, and Pyrite shows what would change before you apply them (Show what would change, then Apply these rules); after that you change every item on its own. You answer them at the first start, from the page (Answer the questions again) or, on a server without a screen, from a terminal with pyrite.exe network setup (with the engine stopped; on Windows from cmd type start /wait pyrite.exe network setup, or give the options and --yes: network setup -h lists them).
- If you answer “only from the internet” from a first-start page opened on another computer, Pyrite doesn't lock you out: it tells you to do it again from an SSH tunnel (or to choose “private network”).
- Opening the engine to the whole network asks for a confirmation of its own, and the port of the engine can't be the one of an app or of an entrance. If the engine was started with
--httpon the command line, the previews say so: it wins over the file.
24 /The Windows firewall
For the other computers to open the portal and the apps, the Windows firewall must let pyrite.exe in. Pyrite now reads how the firewall is, shows it, and can make the rule. It uses one rule for the program (inbound, private and domain networks), not one for each port: it covers the engine, every app and the apps of tomorrow. It is called Pyrite (pyrite-…), with the name of the service.
When the rule is made
- When you install the service (
pyrite.exe service install, Command Prompt as administrator) the rule is made by itself, if Pyrite listens in the network. To skip it:pyrite.exe service install --no-firewall.service uninstallremoves only that rule, not the others. - With the command, in a Command Prompt opened as administrator:
pyrite.exe firewall openmakes the rule (TCP only; if the right rule is already there it does nothing, and if there is one with the same name that does not open, it touches nothing and says to runcloseand thenopen),pyrite.exe firewall closeremoves it. Pyrite considers as its own only the rule with its name and its program: from a copy of the folder it never touches the rule of the real engine.pyrite.exe firewall statussays how the firewall is and needs no administrator rights. Without administrator rightsopenandclosetouch nothing: they print the command to run again as administrator. - With the button, from the console: see below.
- With the engine on, the service never changes the firewall. It runs without administrator rights, and it must stay so: an engine that could change its own firewall would be a door for whoever breaks into it.
The box “Windows firewall” in Network rules
At the top of the Network rules page the box says in one sentence how the firewall is for Pyrite:
- Lets Pyrite in: there is an active rule for the program, for all its ports, if the network of this computer is marked as private or domain. Pyrite cannot know which network is in use: on a public network the rule does not apply. Nothing else to do.
- Only some ports: the rule covers only some ports; the other ones, those of new apps too, don't open from the other computers.
- No rule: from the other computers nothing opens.
- Firewall off in the private and domain networks: everything is reachable, even without a rule.
- Decided by the company policy: the local rules are ignored, Pyrite cannot open the network by itself; ask the network administrator to allow the program.
- Blocked: Windows blocks all the incoming connections, so the rules do not count. Opening is not enough: the block must be removed in the Windows firewall settings. There is no button. If the block is only on one of the two kinds of network (private or domain), the box says which: the state is then read on the other kind, and one more sentence tells where Windows blocks.
- Forbidden: there is a rule that blocks this very program. Opening is not enough: that rule must be removed. There is no button.
- Not known: Pyrite cannot read the firewall, or it finds rules it doesn't understand (for example a rule that blocks all the ports and cannot be weighed). When in doubt, it never says “open”.
“Lets Pyrite in” and “open” always mean “if the network of this computer is marked as private or domain”. Below the state the box lists the apps switched on in the network, each with its port: open, closed by the firewall or not known. The button Open Pyrite on the local network is there only if all these are true: the state is “No rule” or “Only some ports”, whoever looks is an Owner, the page is opened from the computer of the engine, Pyrite runs with the icon (not as a service), somebody is in front of the screen, Pyrite was not started as administrator (Windows would ask for nothing), and Windows on this computer is not set to give administrator rights without asking (if Pyrite cannot read the setting, there is no button). When you press it and confirm, Windows shows its own request, and it is for netsh.exe, a program of Windows, not for pyrite.exe: Pyrite itself never runs with administrator rights because of the button. One request at a time; no black window. The result (rule made, not made, request refused) is written in the History within two minutes; then reload the page. In every other case the box does not show the button but the command to give by hand on the server (pyrite.exe firewall open as administrator): when Pyrite runs as a service, when nobody is in front of the screen, when Pyrite is already started as administrator, when Windows gives administrator rights without asking, and in the states Blocked and Forbidden the command is not enough either.
The limits
- If the computer has another firewall (of an antivirus, for example) or the network has one, Pyrite doesn't see it: the box says so.
- With a company policy that decides the rules, or rules written in a way Pyrite doesn't read, Pyrite writes “not known”, never “open”. Which network profile is in use at this moment cannot be read: Pyrite reasons on “private or domain”, and the texts say “if the network of this computer is marked as private or domain”.
- The rule opens only the TCP protocol.
- The request of Windows shows up in the session where Pyrite runs, not in the one of whoever has the browser (for example two people connected to the same server by remote desktop): the button is meant for whoever sits at the server.
- When Windows blocks everything, or there is a block for Pyrite, the Overview and the card of the app show a warning too (if there are apps switched on in the network).
- This part has not yet been tried on a real Windows: see ISTRUZIONI-PROVA.html.
25 /Sign-in: one sign-in, wrong attempts, the console
One sign-in even with a name for each app
When every app has its own name (for example booking.app.example.com), whoever opens an app without being signed in goes through the portal, types the password once and comes back to the app by itself. The step uses a code that works once, for one minute, only for that app and only in the browser that asked for it. No cookie is valid for the whole domain. With name + port (the usual way) nothing changes.
- Sign out closes everything. Sign out of the portal or of an app closes at once the apps with another name too. So do Sign out of all sessions, a new password and a disabled person.
- Shared computers. Whoever signs in to the portal after another person, from the same browser, also closes the apps that person had opened (when every app has its name).
- Two connections. Someone who goes out to the internet with two addresses (for example IPv4 and IPv6, or a proxy with several exits) enters the apps. If the link to enter an app arrives from a different connection than the one that asked the portal, before entering a page appears: “You are entering app as name (email)”, with Continue and Leave. If the name is yours, press Continue. A notice appears in the Engine history, at most one a day for each person and address, with the two addresses: usually it is the same person; if it happens to many people, the portal and the apps don't have the same DNS records (for example IPv6 only on the portal) and it is better to align them.
- A link that no longer works. A link to enter an app prepared by another browser, or an entrance to the portal from its sign-in page left open for a long time, stops with “This link to open the app is no longer valid”: open the app again from the portal. Pages of other sites can no longer block the sign-in to the portal.
Several engines on the same server
Every engine has its own cookies, so two engines on the same server (on different ports) no longer throw each other out. Whoever was signed in before the update stays signed in. Be careful: a folder of the engine copied as it is carries its identifier with it, and the two copies on the same server go back to throwing each other out.
Wrong attempts
The engine counts the wrong passwords for every real address, also behind a tunnel. Whoever makes mistakes from the internet no longer blocks the people in the local network.
- From the internet, 5 wrong attempts in 15 minutes block that address, and 10 wrong attempts on the same email (from any address) block that email for one hour, only from the internet: from the network you can always sign in.
- The console has its own count, separate from the portal's.
- The limits are changed in Network rules, section The thresholds of wrong attempts.
- The limit holds even when the attempts arrive all at the same instant; from the internet a whole home IPv6 network counts as one address. A slow connection (or one made to be slow) no longer blocks the others of the same computer or network.
- During an attack from the internet the events don't fill up: after 20 blocks in an hour there is only one notice (one text for the addresses and one for the emails). The blocks from the local network and those of the emails of the people in the directory always have their event; the cap of 20 an hour holds for each entrance and only for the emails that don't exist.
The console only from some addresses
In Network rules, section The console, you can say from which addresses or networks the console opens (for example the VPN, or only the server itself). Empty means from the whole network. The list must also include the address you are using now. From another address the sign-in page says so at once, before the password. The portal stays open to everyone.
- “Only this computer” means every program that runs on the server, apps included.
- If you use the console through a proxy on the same server, the page tells you that from there you can't limit the console to a list, and what to do: leave it empty, or save it from the server without the proxy, or from an SSH tunnel.
- The console doesn't exist from the internet, not even with a console session opened from the local network: the keys of the console and of the Data panels are valid only from the entrance they were born at.
- In the Profile, next to the sessions opened from the internet it says “from the internet”.
The console closes by itself
After 30 minutes without use the console asks again for the password (and for the code, for whoever has two-factor authentication). The page goes back to the sign-in by itself and writes “Session closed after N minutes without use”. A page left open on a screen that nobody touches doesn't keep the session alive: only what the person does counts.
- The time is changed in Network rules, section The console, from 5 minutes to 12 hours. The change is valid at once, also for whoever is already inside. A session that has closed stays closed, even if you make the time longer afterwards.
- The upper limit: a session never lasts more than 12 hours from the sign-in, even if it is used all the time. Renewing the key or changing the password doesn't make it start again.
- After a restart of the engine everybody signs in again (the sessions are kept only in memory).
- The limit, said plainly. Inside the time, a console left open on an unlocked desktop can be used by whoever sits down. The time shortens the window, it doesn't replace the lock of the screen: lock the desktop of the server when you leave it (see The console and the levels).
- Working in the Data panel of an app counts as use of the console (the gestures inside the frame are listened to). When the session is closed, the Data panels opened from that session fall at once too.
- Short times. The field of the minutes also accepts 5: with such a short time follow the long operations (backups, imports, updates) on the page, because if nobody touches the page for that long the console closes even while the operation is running. The exception is a long request you started yourself (an upload, an export): while it lasts it keeps the session alive, but for 30 minutes at most, even if the chosen time is shorter.
- Console sessions. In the Profile, box Console sessions, everybody sees their own (address, from where, when it was opened, last use) and can close one of them or all the others. In the card of a person, an Owner sees and closes the sessions of the others; this stays in the History. Closing is immediate. (Sessions that close by themselves leave no line in the History.)
26 /HTTPS and certificates
Without a certificate the engine works in HTTP: passwords and data travel in clear text on the network, and the Overview says so. From Engine settings → Certificates (Owners only, in both console layouts) you turn HTTPS on. One certificate is enough for the engine and for every app port: a certificate is valid for a name, not for a port. Today's addresses (http://SERVER:8080/, http://SERVER:8105/, bookmarks) keep working: the engine sends them to https:// on the same port. The apps' processes stay in plain HTTP on 127.0.0.1, inside the server. At the top of the page: the mode, the names covered, the expiry, who signed, and Check (a real test of every port). First write the names and addresses people use to reach the server: the computer name, the full name in the domain, the IP address.
- a. No certificate (HTTP): the engine keeps working in HTTP. Fine only for a test.
- b. Request for the company CA (Active Directory Certificate Services, AD CS, or another CA).
- Is there a CA? On a PC in the domain, in a command prompt:
certutil -dump(orcertutil -TCAInfo). An entryConfig:with a server and a CA name means yes. If nothing is found, use the internal CA (d). - Create the request: the private key is born on the server and never leaves it. Download the request (
pyrite.csr). - Have it signed, on a PC in the domain, as someone who may request certificates:
certreq -submit -attrib "CertificateTemplate:WebServer" pyrite.csr pyrite.cer(a window asks which CA). If it waits for approval: the CA administrator approves it, thencertreq -retrieve RequestId pyrite.cer. Or with the web page of the CA:http://CA-SERVER/certsrv→ Request a certificate → advanced certificate request → paste the text ofpyrite.csr→ template Web Server → Submit → Base 64 encoded → Download certificate (or the chain,.p7b). - Upload the
.cer,.crt,.pemor.p7byou received: the engine checks that it belongs to the request and covers the names, then uses it at once. The domain PCs already trust an enterprise CA: nothing to distribute.
- Is there a CA? On a PC in the domain, in a command prompt:
- c. Upload a file: a
.pfx/.p12with its password (both the ones Windows exports today, AES-256 with SHA-256, and the old ones, 3DES or RC2 with SHA-1), or.pem(certificate and key, in one file or two). The engine checks that the key belongs to the certificate, that it is valid today, that it is for a web server, that the key is strong enough and that it covers the names; if it covers only some names it asks before using it. The password is used only to open the file and is not written anywhere. If a.pfxis still refused:openssl pkcs12 -in certificate.pfx -out pyrite.pem -noencand upload the.pem. - d. Internal CA created by Pyrite: Create the internal CA creates a certification authority and the server certificate (with the names, plus
localhostand127.0.0.1) without turning HTTPS on: first distribute the CA to the PCs, then press Turn HTTPS on. The server certificate lasts 397 days and renews itself 30 days before it expires, with the same CA. The CA may sign only web server certificates and only for these exact names and addresses (a new name needs a new CA, and a new CA must be distributed again to all the PCs: so first choose all the names, the engine's and, if you want them, the domain of the apps, and only then create the CA): if someone stole its key, they couldn't pretend to be internet sites or other servers of the domain, nor sign programs. Replacing the CA (New CA), the key of the previous one is deleted at once; its public certificate stays for reference (remove it from the PCs). Distributepyrite-ca.certo the PCs with a group policy:- download it from the page (Download the CA certificate);
- on a server with Group Policy Management (
gpmc.msc): create (or edit) a Group Policy Object linked to the organizational unit of the PCs, or to the domain; - Computer Configuration → Policies → Windows Settings → Security Settings → Public Key Policies → Trusted Root Certification Authorities → right click → Import →
pyrite-ca.cer→ Next until the end; - the PCs receive it at the next policy refresh (at restart, or within about 90 minutes; at once with
gpupdate /force); - check on a PC:
certlm.msc→ Trusted Root Certification Authorities → Certificates: the Pyrite CA is there, with the thumbprint shown on the page.
pyrite-ca.cer→ Install Certificate → Local Machine → Place all certificates in the following store → Trusted Root Certification Authorities. Edge and Chrome use the certificates of Windows; Firefox too in recent versions (otherwise import it in its settings).
What people see the first time. With a certificate the PCs trust (company CA, or the internal CA already distributed): the padlock and nothing else; the old http:// addresses go to https:// by themselves, and people sign in to the portal once more (the sign-in of the plain address doesn't carry over). With the internal CA not yet on the PCs, the browser says the connection is not private: distribute the CA first, then turn HTTPS on, and don't teach people to click through the warning. Whoever arrives with a name the certificate doesn't cover (for example the short name when only the full one is in the certificate) sees the warning: the Certificates page and the Overview list those names.
Expiry. The engine checks every day: in the Overview and in the events at 30, 14, 7 and 1 day before; an expired certificate is shown in red. Nothing is turned off by itself.
Emergency exit. If HTTPS is misconfigured and the console doesn't open from the network: from the server itself the console always opens in plain HTTP at http://127.0.0.1:8080/console/. If not even that works: stop the engine (icon → Exit) and in a command window in the folder type pyrite.exe certificates off (pyrite.exe certificates status says how it is set). At the next start the engine works in HTTP; the certificate stays, and you turn HTTPS back on from the page. If HTTPS is on but the certificate can't be read (for example after moving the engine to another computer), or the certificates state file is damaged, the apps don't answer in clear text from the network (closed by default): they show a page that says to tell whoever manages Pyrite. With a damaged state file the page offers Repair the state (it keeps a copy of the damaged file and rebuilds the state from the folders, internal CA included); certificates off repairs it too. Going back to HTTP, people sign in again with their password: in HTTPS the sign-in cookie has another name (__Host-), so it doesn't get in the way. On the server itself the icon and the small window always open http://127.0.0.1, so there is no certificate warning there.
Where the keys are. In control\certificati\. Only SYSTEM, the Administrators and the account the engine runs as can open that folder (the engine sets these permissions, without inheriting those of the engine folder); if the engine later runs as another account, give that account control of the folder (icacls) or create the certificate again. The keys are also protected with Windows DPAPI of this computer: that protects against copying the files to another computer, not against the other users of this one (that is the job of the folder permissions). No route of the engine serves them; they are not in the events, the logs, the backups or the restore point of the engine update, and an engine update or update-restore doesn't touch them. Moving the engine to a new computer: create the certificate again (with the internal CA, a new CA to distribute again). HSTS is off by default; turned on (page, More), the browsers that see it refuse plain HTTP for that name, on every port, for 180 days, even after certificates off. To go back to HTTP after HSTS: turn HSTS off and leave HTTPS on for a few days; for 180 days the engine tells the browsers that come by in HTTPS to forget the rule.
27 /Let's Encrypt, Cloudflare and more certificates
All of this is in the Certificates page (HTTPS and certificates), for Owners.
More than one certificate
Pyrite can keep several certificates and chooses by itself the right one for every name: first the exact name, then the one with an asterisk, otherwise the default one. To add one: Certificates → Upload a file → Add it next to the default one, for its own names. In the same page you choose which one is the default (Use as the default certificate) and remove the ones you don't need. Without extra certificates nothing changes.
One certificate for all the apps
A certificate *.app.example.com is valid for all the apps under app.example.com (booking.app.example.com, orders.app.example.com…), on one level only, and the names of the single apps don't end up in the public registers of the certificates. You can get it from Let's Encrypt (below), from the company CA (write *.app.example.com among the names of the engine) or from the internal CA: with the names on, the internal CA also covers the domain of the apps and the names of the portal. If the CA was created before, the page says a new one is needed, to be distributed again to the PCs.
Let's Encrypt with Cloudflare
Suggested; it also works for the apps used only in the local network.
- Certificates → Let's Encrypt and the DNS → open the Let's Encrypt account (Open the account: accept the terms of use; the email is optional).
- Put the Cloudflare key (Cloudflare key for the check in the DNS, then Test and save). The smallest key: on Cloudflare, My Profile → API Tokens → Create Token → Edit zone DNS (Zone · DNS · Edit), only the zone of your domain and, if possible, with the filter on the public IP address of the server. A key of the account works too. Pyrite tests it at once (it writes and removes a test record) and then never shows it again: you only see its last characters. It stays only on this server, protected like the keys of the certificates; if the engine moves to another computer, put it back.
- Certificates from Let's Encrypt → Request the certificate (by default the single certificate for the apps plus the portal). The page follows the steps while they happen.
For more separation: a separate domain used only for the checks, and in the DNS of your domain a CNAME _acme-challenge.app.example.com pointing to _acme-challenge. followed by the domain for the checks; with a split internal DNS, the same CNAME in the internal DNS too. Before the first real request Pyrite makes a trial run with the test environment of Let's Encrypt, so a mistake doesn't use the limits. The “test” account is only for trying: its certificates are not put in use.
- A
*.app.example.comin the DNS (dynamic DNS, a tunnel with the asterisk) or an internal DNS with a split zone no longer block the certificate. - If the firewall of the network sends the DNS questions going out to a server of its own, Pyrite notices, waits a minute and asks for the check (the page says so while it happens).
- If the zone on Cloudflare is not active yet (the registrar doesn't use the Cloudflare servers yet), the page says so and Pyrite asks for nothing: it tries again when Cloudflare says “active”.
- If Pyrite can't remove a check record from the DNS (Cloudflare doesn't answer), it removes it at the next round; if you remove the key, it removes them before. The ones that stay are listed in the page, to be removed by hand on Cloudflare.
Let's Encrypt with port 443
Without Cloudflare, only with the port open to Pyrite: the router sends the public port 443 to the internet entrance of Pyrite (Network rules, open port) and Pyrite answers the check by itself (Request with port 443). It makes one certificate for every name on the internet (the portal and the apps open to the internet), with no asterisks; with a tunnel or a proxy you need the DNS. Pyrite doesn't use port 80.
Renewal and notices
- Pyrite checks every 6 hours and renews by itself when a third of the duration is left (for the 90 days of Let's Encrypt: at 30 days). If it doesn't manage, it tries again with longer and longer pauses; a notice appears in the Overview, with the reason, only if the problem lasts and less than 14 days are left. Renew now and Stop renewing it are in the page.
- For every certificate you uploaded by hand there are expiry notices (30, 14, 7 and 1 day, and expired). The ones of Let's Encrypt renew by themselves and don't warn at 30 days.
- If you upload a certificate in place of a Let's Encrypt one, Pyrite stops renewing the old one and doesn't put it back in use.
- If Let's Encrypt writes that a certificate has to be replaced (Pyrite 0.7.5 doesn't ask about it by itself): Renew now in the Certificates page.
- If a name of the portal or of an app is not covered by any certificate, the Overview says so, with the remedy. An Admin sees in the Overview only the names of their own apps.
- Every Let's Encrypt certificate goes into the public registers (Certificate Transparency) with its names; with the asterisk only
*.app.example.comis seen.
Going out to the internet
Let's Encrypt and Cloudflare are reached in HTTPS (port 443 going out). If your network goes out through a proxy, put it in the environment variable HTTPS_PROXY of the user Pyrite runs as. The check that the record has spread uses the DNS (port 53 going out, to the Cloudflare servers): if it is closed, Pyrite waits a minute and goes on.
Tunnel or proxy in front
If the HTTPS from the internet is done by the tunnel (for example Cloudflare) or by a proxy, the Overview says so instead of the notice “you are in HTTP”. To protect the local network too, turn on the HTTPS of Pyrite anyway (for example with Let's Encrypt through the DNS).
From the internet with an open port
From the internet, public certificates only. With the port open on the router, Pyrite never shows the certificate of the internal CA from the internet, nor a certificate that contains internal addresses (192.168…, 10…, 127.0.0.1) or the name of the computer without a domain. Whoever connects without a name (by IP address, as the scanners of the internet do), with a name that Pyrite doesn't have, or with the name of an app only for the inside receives no certificate: the connection closes at once (a connection error in the browser). The same happens for the portal and for the apps open to the internet, until they have a public certificate for their name (Let's Encrypt, or an uploaded one). Note: if the internal CA covers that name, the Certificates page shows it as covered even though it doesn't open from the internet: always check from outside. So from the internet the names and the addresses of the internal network cannot be read. From the network, from this computer and with a tunnel or a proxy in front nothing changes.
If something goes wrong
- If the file of the state of the certificates can't be read, Pyrite changes nothing by itself; after Repair the state (Certificates page) or
certificates offit goes on renewing the Let's Encrypt certificates. - After going back to 0.7.4 and returning to 0.7.5, even if before the first start you use
pyrite.exe certificates off, the extra Let's Encrypt certificates come back into use and Pyrite goes on renewing them.
28 /The engine history
The events of the engine (who started an app, who gave an access, who signed in to the console, who changed a setting…) are now in a history of their own, the file control\storico\storico.db, outside the registry. From the console nobody deletes or changes them, not even an Owner: emptying the technical logs or putting back a backup of the registry doesn't touch them.
- Who, on whom, where. Every event says who did it, also when it comes from an app (an uploaded file, a restored record), on whom and on which app. For sign-ins and for the actions from the console there is also the address they came from: only an Owner sees it.
- The page “Engine history” (in the menu, in place of “Events”). You filter by period, app, person (who acted or on whom), type and severity, and you can go back in time without limits. An Owner sees everything and can download the view as a CSV file (Download CSV; the download is recorded in the history). An Admin sees the events of their apps, from 0.7.5 on, with the Owners written as “Owner” (no emails of Owners, no row numbers). A User doesn't see the page.
- Events up to 0.7.4. At the update the events of 0.7.4 are copied into the history, marked “up to 0.7.4”: only an Owner sees them. The originals stay in the technical Logs page, which has the filter Events up to 0.7.4.
- Fingerprints and “Check”. Every row has a fingerprint tied to the one before: if someone with the keys of the server removes or changes a row directly in the file, Pyrite notices (every night at 4:50, or when an Owner presses Check) and says so in the Overview, also after a restart. If the file disappears, Pyrite says so at the restart. Pyrite also remembers, outside the file, the last row it wrote: if the history is put back from an old copy, or rows are added or redone in the file, Check sees it.
- How long. One year by default. An Owner can make it longer, up to ten years (in the history page or in Engine settings), but not shorter: there is no way to do it. Every night at 4:40 only the events older than the chosen duration are removed.
- The copies. The history is not in the backups of the registry. Instead, every night after the 3:00 backups Pyrite makes a copy in
control\storico\copieand keeps the last seven; with the network copy on, the copies also go to the network folder. Every copy, also the one on the network, can be checked from the page: Pyrite says whether it is whole and whether it says the same as the history of now. - The space. The page shows how much the history takes (with the copies) and how much it will grow in a year, estimated from the last 30 days (with 50 people, tens of MB a year). The Overview warns if less than 1 GB is left on the disk, or if the history is more than a fifth of the free space.
- If it can't be written (full disk, permissions) the actions go on anyway: the Overview says so and the events enter the history as soon as possible. In the meantime they are also kept in
control\storico-fuori.jsonland go back in by themselves: even emptying the technical logs doesn't lose them. If some rows of that reserve file are damaged, the others go in anyway, the history says so with a notice, and the file with the damaged rows stays incontrol, to be looked at. Stopping the engine while many events are going back in doesn't wait for all of them: the rest goes in at the next start. - The SQL console of the Advanced pages no longer accepts
VACUUM(as it already didn't acceptATTACH). - Going back to 0.7.4 (
update-restore) doesn't touch the history nor its copies; back on 0.7.5, the events written meanwhile by 0.7.4 enter the history, without duplicates. - If you copy the folder of the engine by hand, copy
control\storicotoo (with the copies inside). - The change history of the data of an app. When a signed-in person uses a function of the app that writes the data by itself (a route written by the app), the app's change history carries their name; the scheduled jobs of the app and the calls without a sign-in stay “app script”. The apps don't need to be changed.
29 /Copy of the backups to a network folder
The backups (every night, of the engine and of the apps) stay on the engine's disk: if that disk breaks, they are lost with it. Engine settings → Copy of the backups to a network folder (Owners) copies them every day to a network folder (a NAS, a shared folder of a server) or to another disk.
Setting it up
- On the NAS make a shared folder only for these copies, for example
\\nas\backup\pyrite, closed to everyone else (see Security). - Give the permission on it to the account the engine runs as (see Permissions).
- In the console: Engine settings, section Copy of the backups to a network folder. Write the folder (
\\nas\backup\pyrite; another drive such asD:\pyrite-copiesworks too, but not a mapped letter such asZ:: it exists only for whoever mapped it), the time (default 05:00, after the nightly backups at 3:00: both are the computer's time), the days and the months to keep, turn on Copy every day and Save. The folder can't be inside the engine's folder nor in a Windows folder; if it is on the same disk as the engine the page warns you. - Press Test the folder: it writes a test file, reads it back, compares it and removes it, and tells the free space and the account. Then Copy now and wait for «Last copy done».
What ends up in the folder. The engine writes only in <folder>\<COMPUTER NAME>, with the same paths as in the engine's folder: control\pb_data\backups\ (backups of the engine registry: people, access, settings, list of the apps), apps\<app>\state\pb_data\backups\ (backups of the apps), apps\<app>\app.json and release\ (the code of the apps), archivio\ (the archived apps, which exist only there) and pyrite-giri\ (one manifest per copy: date, files, SHA-256 fingerprints, outcome). Not copied: the keys in control\certificati (they belong to the computer), the safety copies of the app updates (control\aggiornamenti_app), the restore points of the engine (control\aggiornamenti), the logs, and the data of an app outside its backups. Nor the native automatic backups of PocketBase (names starting with @auto_pb_backup_, which exist only if someone turned them on in the native settings of an app or of the engine): they hold the same data as Pyrite's nightly backups, which are all copied and are enough to put back the registry and the apps. There is also pyrite-versioni\<date>\: the previous version of a file of the code or of the archive that changed or was removed in the engine.
How it copies. Every file all or nothing: written with a temporary name, read back from the folder and compared with the original (SHA-256), and only then renamed to its final name in the folder; the originals are never touched. A file already there and equal is not copied again. The old copies are removed only after a copy where every file was copied and checked, and only the files the engine wrote (listed in its manifests): never other files of the folder. With the defaults you keep every backup of the last 14 days (twice the 7 the engine keeps on its disk) and, for the 12 months before, the most recent of each month for every app and for the registry; archived apps stay while they are in the Archive and for 12 more months after you delete them for good; the code of the apps is always the current one. One copy at a time, at most 8 hours (the files already copied stay: the next copy goes on from there); if the nightly backups are still running, the copy waits for them. It is the scheduled job pyrite_copia_rete of the engine (Advanced → Crons). All the scheduled jobs of the engine count in the computer's time; those of the apps stay in UTC. If the engine is off at the time of the copy and the last copy done is more than 24 hours old, the copy starts by itself 10 minutes after the engine starts; a copy interrupted by a shutdown shows up after the restart as not done.
Safeguards. Writing goes without the Windows cache and so does the read back (only the cache of the disk or of the NAS remains). A backup already copied is never overwritten: if in the engine a backup with the same name changed (damaged disk, virus that encrypts), the copy fails, says so, and the one on the network stays as it was. The code of the apps and the archive do change: the previous version goes to pyrite-versioni\ and stays there for the days kept, and the folder of the app always has the current code. An app registered without its folder in the engine, or a folder of the engine that can't be read, make the copy fail and stop the cleaning (the network copy is exactly what puts them back). At every copy a part of the files already on the network (up to 2 GB, the ones checked longest ago first) is read back in full: a damaged copy of a file the engine still has is made again (event), one of a file the engine no longer has is an error event. The copy never reads or writes through a link (junction) in the network folder, and checks where every file it writes really is. The cleaning is skipped if the computer's time is before the last copy or more than 48 hours after the last copy done (with a warning: check the time; if the current time is right and the most recent manifest comes from a wrong clock, copy it out of pyrite-giri\ and then delete it), removes only the files with the names and in the folders the engine writes, and always leaves at least the last 3 checked backups of every app and of the registry. When space runs out the copy first removes the expired copies the engine no longer has and tries once more. If the computer folder holds the copies of another engine with the same computer name, the copy stops without writing anything: choose another folder.
If it fails you see it. An error event with the reason in plain words (folder not reachable, access denied with the engine's account and what to do, out of space, different fingerprint, too slow); in the Overview a red box when the copy is on and the last copy done is more than 26 hours old (or there has been none); on the Backup page a line with the last copy done (green; yellow if the last copy failed, red after 26 hours).
Permissions on the folder
No password is stored: the copy runs with the engine's account (the section shows it, and so does the test).
- Computer in the domain, engine running as SYSTEM (the scheduled task of the engine, or a service): on the network the engine is the computer account,
DOMAIN\NAME$. On the share and in the Security tab of the folder give Modify to that computer (in Windows: Add → Object Types → Computers; on the NAS choose the computer from the domain). - Engine running as a user (scheduled task with a user, «Run whether user is logged on or not»): give Modify to that user. Its password is kept by Windows (Task Scheduler), not by Pyrite.
- Computer not in a domain, engine as SYSTEM: SYSTEM has no account on the network. Run the engine's task with a user the NAS knows.
- A separate account with its own password, only for the copy: not possible yet. It needs a safe for secrets in the engine (planned for later); until then the permission goes to the engine's account.
Security
- The backups contain all the data of the apps, the people and the fingerprints of their passwords: the folder is only for the engine's account and whoever manages Pyrite. Not a folder that everyone maps.
- Turn on the snapshots of the NAS (read-only versions taken at set times and kept for weeks): a virus that encrypts files and reaches the share (the engine's account can write there) can't touch them.
- Better a NAS in another room, and from time to time a copy that stays disconnected.
- Whoever changes the folder (an Owner) makes the engine present itself to that server with its account (on the network, usually the computer account): a server chosen on purpose could collect its network credentials. That's why every change of the folder is an event (who, from which folder to which), and the folder can't be this same computer (
localhost,127.0.0.1, its name or its addresses) nor an administrative share (C$,ADMIN$). Give the Owner level only to who needs it and look at the settings events.
Putting back an app from a copy
- In the network folder open
<COMPUTER NAME>\apps\<app>\state\pb_data\backups\and choose the backup (the name has date and time:auto_20261105_030000.zip). - Copy it (copy, don't move) into the same folder of the engine:
apps\<app>\state\pb_data\backups\. - Console → Backup → the app: the file is in the list. Press Restore: the engine stops the app, keeps a copy of the current data (
state\copia_prima_del_ripristino_…), puts back the backup and starts the app again.
An app whose whole folder is gone: copy apps\<app>\ from the network folder (code and backups) into apps\ of the engine, then Rescan folders, start it and restore the backup as above. An archived app: copy archivio\<entry>\ back into archivio\ of the engine and use the Archive page.
Restoring the engine registry
The registry (people, levels, groups, who enters which app, settings, list of the apps) is restored with the engine stopped. Everything changed after that backup (new people, passwords, access) is lost.
- Choose the backup: in
control\pb_data\backups\of the engine, or in the network folder (<COMPUTER NAME>\control\pb_data\backups\). - Icon near the clock → Exit.
- Copy the whole folder
control\pb_datato a folder outside the engine (copy, don't move: it is the way back). - Extract the zip (right click → Extract All) into a folder outside the engine: inside there are
data.db,auxiliary.dband maybestorage\. - In
control\pb_datadeletedata.db-wal,data.db-shm,auxiliary.db-wal,auxiliary.db-shmif they are there, then copy the extracted files over the ones incontrol\pb_data(replace). Don't touchcontrol\pb_data\backups. - Start the engine and check people and apps in the console. If something is wrong: Exit, put back the folder copied at step 3, start again.
A new computer (the old disk is gone)
- Put
pyrite.exe(the same version) in a new folder; don't start it yet. - In the engine's folder create by hand the folder
control\pb_data(the engine hasn't started yet, so it isn't there). Then from the network folder<OLD COMPUTER NAME>\copy into the engine's foldercontrol\pb_data\backups\(inside thecontrol\pb_datajust created),apps\andarchivio\(notpyrite-giri\andpyrite-versioni\). - Put back the registry from its most recent backup (steps 4 and 5 above).
- Start the engine: the apps are there, with their code and empty data. For each app with a database: Backup → the app → the most recent backup → Restore.
- HTTPS: the certificate is not in the copy (its keys belong to the old computer): make it again from the Certificates page. The network copy comes back on with the registry and writes in the folder with the new computer's name.
30 /Moving Pyrite to another computer
This is for when the old computer still works and you want Pyrite on a new one. If the old disk is gone, see A new computer (the old disk is gone) above.
- Stop the engine first (icon near the clock → Exit, or stop the service), so that no file is being written during the copy.
- Copy the whole folder of Pyrite, not only
pyrite.exe: it must containcontrol,appsandlogs. The registry of the engine (people, levels, groups, the list of the apps) is the filecontrol\pb_data\data.db: without it the new engine starts empty. - It is safer to make a ZIP of the folder and to extract it on the new computer into a new, empty folder, rather than copying file by file.
- How to know the copy worked. At the first start the page of the first Owner does not appear: you go to the sign-in page and the people are there. If the page of the first Owner appears, the copy is incomplete (usually
control\pb_data\data.dbis missing). Don't create anything: close the engine, and copy again.
Incomplete copy? Pyrite says it by itself. Ifcontrol\pb_data\data.dbis missing but the folder shows a past life (old logs, apps with their data, the history), the page of the first Owner shows a warning and does not go on until you tick “Yes, it is a new engine”; the same warning is written in the window of the engine and inlogs\engine.log(it works also when Pyrite starts from the icon or as a service: then the log and the page tell it); from a terminal,pyrite.exe owner create EMAILstops and asks for--new-engine. If it is a copy: close the engine and make the copy again, with the whole folder. Only if it really is a new engine, tick the box (or use--new-engine): the History records it. The warning goes away by itself when the registry is back. A really new engine, with an empty folder, shows no warning. - What is tied to the computer and must be done again. The HTTPS certificate: its keys belong to the old computer, so make it again from the Certificates page (see A new computer above and HTTPS and certificates). The two-factor authentication: the key of the codes opens only on the computer that made it, so whoever had it is shown as “to be turned on again” (see The key and the backups).
- Windows settings to do again. The firewall: the rule is for the file on that computer. On the new computer
pyrite.exe firewall statussays if it is there;pyrite.exe firewall open(as administrator) makes it, and installing the service makes it by itself (see The Windows firewall; Windows may also ask at the first start, see First start). And the start with Windows (the icon's menu, the service or the scheduled task: see Pyrite as a Windows service). - Keep the old computer off, and its folder intact, for a few days. It is the way back. Don't start the two engines together on the same network: a folder copied as it is carries its identifier with it, and the two copies throw each other out of the sign-in (see Several engines on the same server).
31 /Languages, colors and theme
- Console, portal and the engine's pages are in English and Italian; the language is chosen at the bottom of the pages and holds for the whole engine. The native PocketBase screens (Logs, Advanced, the cards of the records) stay in English.
- Portal, console, sign-in and first-start pages and the window near the clock have a light and a dark theme. Light: white with a hint of sage, graphite buttons, dark teal links. Dark: an almost black background with cream text. The tiles of the apps, the charts and the colors of the states (error, warning, success) keep the Pyrite colors. Links are always underlined.
- The theme (light, dark or as the system) chosen in the portal also holds in the console, and the other way round.
- If the portal home page was customized, the chosen colors stay; the others follow the new palette.
32 /Updating from 0.7.6
It is done as the update from 0.7.5, described below: only pyrite.exe is replaced, the engine makes the restore point by itself and updates everything or nothing. There are no checks to make on the scripts of the apps this time. After the update the small window of the icon and pyrite.exe -v must say alpha 0.7.7 (see “What to check after the update” below). To go back: update-restore, as described below.
What changes by itself
- The console closes after 30 minutes without use. Tell whoever uses it: they will find the sign-in page more often. The time is changed in Network rules (from 5 minutes to 12 hours); see The console closes by itself.
- The box Windows firewall appears in Network rules; Load app, the card of an app and the Overview warn when a port is closed by the firewall.
- The apps waiting for approval send an email to the Owners, if the mail is set up (see Apps waiting for approval).
- If a copy of the folder lacks the registry, Pyrite says “incomplete copy?” (see Moving Pyrite to another computer).
- Who signs in again. Whoever was inside the portal stays inside: nobody has to sign in again to the portal. The console, instead, asks for the sign-in again, as after every restart of the engine.
What does not change until you decide
- The firewall stays as it is. The update doesn't make or remove any rule. If the service is already installed and you want the rule, give
pyrite.exe firewall openas administrator (as a service there is no button in the box: see The Windows firewall). - Addresses, ports, accesses, people, data and apps stay where they are.
33 /Updating from 0.7.5
The engine is updated by replacing only pyrite.exe: same name, same folder. Addresses, ports, accesses, data, apps, people and settings stay where they are, and nobody is thrown out: whoever was signed in to the portal stays signed in. To check which program you have, pyrite.exe -v prints the version. This chapter is for reaching 0.7.7 from 0.7.5 as well; whoever comes from 0.7.5 should also read Updating from 0.7.6: what changes by itself applies to them too.
- Check the new
pyrite.exe: in PowerShell, in its folder,Get-FileHash .\pyrite.exe -Algorithm SHA256must give the same SHA-256 fingerprint you received with the file (in the message or on the page you downloaded it from). If it is different, do not start it. - Stop the engine: icon near the clock → Exit. Wait until the icon disappears. If Pyrite runs as a Windows service:
net stop pyrite-…(see Pyrite as a Windows service). - Keep the old program: copy
pyrite.exe(copy it, don't move it) to a folder outside the engine, named after the version you have, for exampleC:\Pyrite-0.7.5\pyrite.exe. It is what you need to go back. - Copy the new
pyrite.exeinto the engine folder, over the old one (same name). Nothing else changes. - Before updating, make the checks on the apps' scripts listed below (Checks to make first) and make a copy of the whole folder with the engine stopped.
- Double-click
pyrite.exe(ornet start pyrite-…). Before changing anything the engine checks the folder (no other engine running on it, files it can write, enough free space on the disk) and makes a restore point by itself: a copy of the engine's data and of the data and settings of the apps, incontrol\aggiornamenti\(the last 2 are kept). Then it updates. Everything or nothing: if something goes wrong, or the computer turns off halfway, the engine puts everything back from the restore point and writes it inlogs\engine.log; start it again to retry, or put back the oldpyrite.exe. If a check doesn't pass, the engine changes nothing, doesn't start and says why (see Problems). - If Windows shows the “Windows Security” window, choose Private networks and allow, as at the first start. Usually it doesn't ask, because the file has the same name in the same folder.
- The console sessions are kept only in memory: after the restart, Owners and Admins sign in again with the same email and password. Coming from 0.7.5, everybody signs in to the portal once more (see below); from 0.7.6, who was inside the portal stays inside.
With many apps and a lot of data the first start takes longer, because the restore point copies the data first. It needs free space on the disk about as large as the data: if it isn't there, the engine changes nothing and says how much it needs.
What changes from 0.7.5
- For the people who use Pyrite, almost nothing. At the first start the engine does the move to the roles by itself and writes a summary: who is an Owner, who is an Admin and of which apps. You find it in the history and in the file
control\passaggio-ruoli.txt. Nobody gains or loses permissions, and passwords and console sessions stay as they were. Whoever was an Admin stays “Admin (as in 0.7.5)” (see The console and the levels). - Coming from 0.7.5, after the update everybody signs in to the portal once more. This happens also to those who come from 0.7.4. From 0.7.6 to 0.7.7 it does not happen: whoever was inside the portal stays inside. It happens again, once, if the engine is moved to another computer, if the folder
control\bigliettiis lost, or if you go back to the previous version withupdate-restore. Nothing else changes for those who use the portal. The foldercontrol\bigliettimust not be copied together with the registry backups: whoever had the registry and a key they can open could make a sign-in ticket. - If you remove an app or a role from an Admin while they have the console open, the console signs them out: they sign in again and find the new situation. If you give them one more app, they stay in and see it at once. When an app is deleted, its Admins sign in again (in 0.7.5 they stayed in).
- Whoever stops being an Admin loses at once the apps they managed. In 0.7.5, in some cases, those apps were kept aside and came back when the person became an Admin again: now they must be assigned again.
- Whoever manages a single unit sees one different sentence: if they type the email of an Owner (creating a person or changing an email) they read “This email cannot be used. Ask the Owner.” instead of “This email is already in the directory.”. The Owner finds in the history who typed it.
- Before sign-in the portal shows only the open-access applications; those that ask for sign-in appear after the person has entered. The sentence that told how many other applications the person had no access to is gone: the portal no longer says how many other applications exist.
- For whoever does not see the Owners, the engine no longer forwards answers it can't check (over 8 MB, or compressed in a format other than gzip): an error that says so appears instead. Remedy: ask for fewer rows at a time, or have an Owner do it.
- The Certificates page and the Overview warn when an app or the portal is open on the internet but has only the internal certificate: from the internet that name doesn't open, a public certificate is needed (Let's Encrypt or uploaded).
Checks to make first on the apps' scripts
0.7.6 narrows the fence around the scripts (see What an app can do). Before updating, for each app, look in the files of apps\APP-NAME\release\pb_hooks and pb_migrations for these things. If you find none, for that app the update changes nothing.
$apis.staticwith a folder outside the app's folder (another app, a folder of the server): it now serves only folders inside the app's folder. If the call is written outside every function (the most common form), the script gives an error when it loads. The files must be brought inside the app's folder.$app.onServe,$app.restart,$app.restoreBackupand$app.rootCmd(also$app.execute()and$app.start()): for the scripts they no longer exist. A script that uses one of these names gets an error (“Object has no member '…'”). They count only when called on$appore.app.unbind,unbindAll,.bind(called on a hook of the app ($app.on…().bind(),onSend(of the mail andunsafeWithoutHooks: they no longer exist. Careful:.bind(is also an ordinary JavaScript function (function.bind(this)), which is fine.- SQL commands with
ATTACHorDETACH(already forbidden, now there is no way left to get them through),VACUUMwritten together with other commands or with a comment, and columns calledattach,detachorvacuumwithout quotes. - Paths that start with a slash (
/release/x.json,\state\x.db): they used to be read from the app's folder, now they are the root of the disk and are refused. Write them without the leading slash (release/x.json,state/x.db). - Network calls to the engine or to another app: the log
apps\APP-NAME\logs\network.log(andnetwork.1.log,network.2.log) keeps only the last 12 MB. Look for the lines with"ip":"127.,"ip":"::1"or the server's address, and those withlocalhostor the server's name in"host", and look at"port": if it is the port of the engine or of another app, stop and decide before updating (after the update that call would be refused). If it is the app's own port or another program of the server, it keeps working. - Other things that are gone:
$os.getenv("HTTP_PROXY")and the like answer empty;new Command(...)doesn't exist;.db()on the database ($app.concurrentDB().db()and the like) gives an empty object: usenewQuery(...),select(...)and the usual functions;$filesystem.local(...)and$os.dirFS(...)on folders that contain links or junctions no longer read or write the files on the other side. For the people who use the apps nothing changes: the backups from the PocketBase console work as before. - Fields or collections with the engine's names. Check that people, groups and apps don't have a field of their own called
unitsorunit, and that there are no collections of your own calledorch_unitsororch_roles. If there are, the update stops, says which name is already taken and changes nothing: start the previous version again, rename the field (or the collection) and update again.
What happens to an app that uses one of these things: the script gets an error in English and that part of the app doesn't work. The engine stops restarting an app with a problem in its files and tries again when the files change or when you press Restart; the Status tab and the events say why. If something is wrong after the update, the way back is update-restore (below).
If you come from 0.7.4
- The live test of this version was done on the update from 0.7.6 and from 0.7.5, with the way back (
update-restore) in both cases. The direct step from 0.7.4 was not tried: if you are still on 0.7.4, it is safer to go through 0.7.5 first (update to 0.7.5, check that everything works, then update to 0.7.7). - The network stays as it is until you change it: Pyrite creates
control\pyrite.jsonwith the values of 0.7.4 (engine on0.0.0.0:8080, apps on the whole network, addresses with the port number, no internet entrance). You change them in Network rules. - The portal sign-in ticket has a name for each engine, and from 0.7.6 the tickets of 0.7.4 no longer let anybody in (everybody signs in once more). Whoever goes back to 0.7.4 must sign in again. On a shared computer it is better that each person presses Sign out of all sessions in the profile (or changes the password).
- From the internet entrance with an open port, a name that has no public certificate gives a connection error, instead of the internal certificate (see Let's Encrypt, Cloudflare and more certificates).
- The first-start code is read in the engine's window, and in
logs\engine.logwhen Pyrite starts from the icon (see First start). The engine history takes the events of 0.7.4, marked “up to 0.7.4” (see The engine history); the “Events” page is now “Engine history”.
What to check after the update
- Click the icon near the clock: the small window says alpha 0.7.7 and the apps are running.
pyrite.exe -vwrites “Pyrite alpha 0.7.7”; in the properties ofpyrite.exe(right click → Properties → Details) the file version is 0.7.7.0. - The sure check: on the engine's Backups page the box Engine updates says “This folder: alpha 0.7.7, updated on … (before: alpha 0.7.6, or alpha 0.7.5 if you come from there)” and shows the restore point as “completed”.
- The event “Engine updated from alpha 0.7.6 to alpha 0.7.7 in … s. Restore point: …” (from alpha 0.7.5 if you come from there) shows in the Overview's Latest events only just after the start: after a few seconds the apps starting and the sign-ins push it away. You find it again in the Engine history.
- Open the file
control\passaggio-ruoli.txt(or the summary in the history) and check who is an Owner and who is an Admin of which apps. Then open People and Groups with an Admin and check that they are as before. - Open the portal and an app with access, like a normal person (signing in again, if you are signed in).
Going back to the previous version
To go back, always run pyrite.exe update-restore --yes BEFORE putting back the old pyrite.exe. If you put back only the exe, the old engine takes the folder for an update: it makes a new restore point and removes the oldest, and after another step forward the point with the data from before the update is gone.
- Stop the engine: icon → Exit (or
net stop pyrite-…). - Open a command prompt (cmd) in the engine's folder (in PowerShell type
.\pyrite.exeinstead ofpyrite.exe) and runpyrite.exe update-restore. It changes nothing: it only says what it would do. Which restore point, from when, and which choices made after the update it undoes: people removed or blocked afterwards become active again, passwords changed afterwards go back to the old ones, the Owners, accesses and apps removed afterwards come back. The plan also says who becomes an Admin again, who is no longer one and to whom the previously managed apps return; who loses the People Admin and App Admin roles received after the update; the units created afterwards and the people created afterwards, who won't be there any more after going back; who loses two-factor authentication and who is left out because the server's key was made again after the point. Write it all down. The prompt comes back at once (see For technicians): wait for the last line, “Nothing has been changed. To go on: pyrite.exe update-restore --yes”. - Run
pyrite.exe update-restore --yesand wait for the line “Done in … s”: it puts back the engine's data and the apps' data and settings as they were before the update. What changed after the update (also what people wrote in the apps in the meantime) is first copied aside, incontrol\aggiornamenti\ritorno_…; the engine never deletes that copy (the Backups page lists it): delete it by hand when you no longer need it. - Only then put back the old program: copy
C:\Pyrite-0.7.5\pyrite.exe(or the one of your previous version) into the engine's folder, over the new one, and start it. If instead you restart the new version, it updates again, with a new restore point. - Check: the small window says the previous version; on the Backups page, box Engine updates, the point of the update is “put back with update-restore”; the apps are running with the data from before the update.
- In the console redo what the command listed: block the people again, change the passwords again, remove again Owners, accesses and apps. People sign in to the portal again, once.
What is lost by going back. The registry goes back to how it was before the update: the level and the managed apps of that time come back, while the units, the roles and the new fields disappear. What was done after the update is lost: people created, levels and managed apps changed, accesses, two-factor authentication turned on. Before going back the engine makes a copy of it in control\aggiornamenti\ritorno_…. The history does not go back: the summary lines stay. If you then restart the new version, the move starts again from the data of the point, gives the same result and writes the summary again (once). The file control\passaggio-ruoli.txt stays where it is and is rewritten.
With the engine running, update-restore refuses and changes nothing. An app archived after the update comes back among the apps, with the data from before the update, and its archived copy stays in archivio\ with the data from when it was archived: they are two copies, so before deleting one see which to keep. An app installed after the update leaves the engine (its files stay in the copy put aside). An app updated from a zip after the engine update goes back to the previous version, and its “Go back to the previous version” is no longer offered: the backup of that update keeps the data of the round that was left behind (it stays on the disk, marked as superseded; the update-restore plan lists it). The same steps are on the engine's Backups page, box Engine updates. update-restore doesn't touch the backups, the copies made before a restore, the logs, the engine history and its copies.
Certificates: 0.7.4 uses only the standard certificate. If from 0.7.5 you go back to 0.7.4 and then forward again, the Let's Encrypt certificates come back by themselves (or Pyrite asks for them); the Let's Encrypt account and the Cloudflare key stay. Extra certificates uploaded by hand must be uploaded again if 0.7.4 removed the folder.
34 /Stopping apps and the engine
- One app: on its page in the console, press Stop (and Start to start it again). Whoever opens it meanwhile sees an “app stopped” page.
- The engine: icon near the clock → Exit (in the menu or in the small window; shutting down Windows stops it in the same orderly way). The apps stop with it; at the next start the engine starts again all the apps, except the ones you stopped from the console.
- To start the engine automatically when Windows starts, use Start with Windows in the menu of the icon.
35 /Pyrite as a Windows service
Besides the icon near the clock, Pyrite can run as a Windows service. As a service it starts by itself when the server is switched on, even if nobody signs in; if it stops because of a failure, Windows starts it again after a minute (up to three times a day); when the server shuts down, Pyrite stops the apps in order. It has no icon and no windows: the console opens at the usual address, also from the server itself (a double click on pyrite.exe opens the console in the browser). The main messages are also in the Windows Event Viewer (Windows Logs → Application, source pyrite-…), besides logs\engine.log.
On a server, do not start Pyrite by double-click with a Windows administrator user. Started that way, the engine and the scripts of all the apps run with full rights on the server. The intended way is the Windows service, which runs with an account of its own (see below).
Install, look, remove
- Install: open the Command Prompt as administrator, go to the folder of Pyrite and type
pyrite.exe service install. The service is calledpyrite-followed by the identifier of the engine (pyrite.exe network statusprints it). - See how it is:
pyrite.exe service status. - Remove:
pyrite.exe service uninstall. Then a double click onpyrite.exebrings the icon back. - At the installation Pyrite turns off Start with Windows of the icon (it is no longer needed) and, if the icon is on, the service waits until you close it (icon, Exit) and takes its place.
- Update: stop the service (
net stop pyrite-…), replacepyrite.exe, start it again (net start pyrite-…).
The account and the folder
- The service runs with an account of its own, which can write only in the folder of Pyrite. If the copy of the backups goes to another disk of this server, give that account the permissions on the folder of the copy, or install with
pyrite.exe service install --localsystem. - The folder must be closed. The service runs
pyrite.exewith an account that has many permissions, so Pyrite installs as a service only if no user without administrator permissions can change its folder. If the folder is open (it happens with aC:\Pyritemade by hand),pyrite.exe service installstops and prints the commands to copy to close it; or put Pyrite inC:\Program Files\Pyrite. Pyrite must be on a disk of the server, not in a network folder. - The firewall. The installation makes the rule of the Windows firewall for the program (inbound, private and domain networks), because the command is given as administrator;
service install --no-firewallskips it, andservice uninstallremoves it. If it cannot make it, it prints the command to run by hand. With the engine on, the service never changes the firewall. Details: The Windows firewall.
The first start can ask for the same choice, with your session (icon) or as a service: see First start.
36 /Starting with nobody logged in
The best way to start Pyrite with nobody signed in is the Windows service (see Pyrite as a Windows service). If you prefer a scheduled task of Windows, or the service can't be used, this is how. You set up the task once. After setting it up, try it as described under “The limits of the scheduled task”.
What to prepare
- An account for the engine, better a dedicated one (a domain account such as
DOMAIN\svc-pyrite, or a local one) and not an administrator. It must be allowed to Log on as a batch job (Local Security Policy → Local Policies → User Rights Assignment). If the PC is in a domain and the copy of the backups goes to a NAS, a domain account is the easiest way (see Permissions on the folder). - The folder of the engine, for example
C:\Pyrite(withpyrite.exeinside; the data, the apps and the logs are created next to it). That account needs Modify on the whole folder (icacls C:\Pyrite /grant "DOMAIN\svc-pyrite:(OI)(CI)M"); the other users do not need it. Don't put it underC:\Program Filesor in a folder of a user profile. - If HTTPS is already on and the engine ran so far under another account (for example your own, with a double click): the folder
control\certificatidoes not inherit the permissions of the engine folder and the new account cannot open it. Give that account control of it (icacls C:\Pyrite\control\certificati /grant "DOMAIN\svc-pyrite:(OI)(CI)F") or make the certificate again; see HTTPS and certificates, “Where the keys are”. Until then the apps do not answer from the network. - The network folder of the backup copy, if you use it: Modify to the same account on the share and on the folder, as written in Copy of the backups to a network folder (the engine's account, here the one of the task, is the one that writes there).
- The firewall, to be set by hand: with nobody signed in, the “Windows Security” window of the first start never appears, so Windows blocks the other computers. The simplest way:
pyrite.exe firewall openin a Command Prompt opened as administrator (check withpyrite.exe firewall status; see The Windows firewall). Or by hand: add an inbound rule for the programC:\Pyrite\pyrite.exe, TCP, private (or domain) profile, for exampleNew-NetFirewallRule -DisplayName "Pyrite" -Direction Inbound -Protocol TCP -Program "C:\Pyrite\pyrite.exe" -Action Allow -Profile Domain,Private. A rule on the program covers the engine (8080) and every app port, so it still works when you add apps. Do it again if the file is replaced by another one in another folder (the rule is for that path). - The first Owner: create the Owner once, before leaving the PC alone: from the first-start page, which opens from another computer of the network with the code that Pyrite writes in
logs\engine.log, or from the command line (pyrite.exe owner create EMAIL, which prints a temporary password).
The scheduled task
The command is C:\Pyrite\pyrite.exe --autostart --unattended.
--autostartis what Start with Windows in the menu of the icon writes: the engine starts on the usual address,0.0.0.0:8080(reachable from the network), writes its messages inlogs\engine.logand does not open any browser.--unattendedsays that nobody is in front of the screen: the program that starts the engine shows no message window (nobody could close it), opens no browser and shows no balloon; the reason of any problem goes intologs\engine.log(the first line says why it works without anybody: “no one at the screen”), and the program ends with an exit code that is not 0. In a task that runs “whether user is logged on or not” the program recognizes by itself that nobody is there, but write the option anyway: it is also what you need for a task that starts when a user signs in and nobody looks at the screen. With a user at the screen and without--unattendedeverything works as usual (windows, browser).
In PowerShell as an administrator:
$c = Get-Credential 'DOMAIN\svc-pyrite' # a window asks for the password, so it does not stay in the command history
$a = New-ScheduledTaskAction -Execute 'C:\Pyrite\pyrite.exe' -Argument '--autostart --unattended' -WorkingDirectory 'C:\Pyrite'
$t = New-ScheduledTaskTrigger -AtStartup
$t.Delay = 'PT1M' # one minute after the start, so the network (and the NAS) is ready
$s = New-ScheduledTaskSettingsSet -RestartCount 3 -RestartInterval (New-TimeSpan -Minutes 1) `
-ExecutionTimeLimit ([TimeSpan]::Zero) -StartWhenAvailable -AllowStartIfOnBatteries `
-DontStopIfGoingOnBatteries -MultipleInstances IgnoreNew
Register-ScheduledTask -TaskName 'Pyrite' -Action $a -Trigger $t -Settings $s `
-User $c.UserName -Password $c.GetNetworkCredential().Password -RunLevel Limited
The same thing by hand: Task Scheduler → Create Task; General: the account, Run whether user is logged on or not, leave Do not store password unticked (the password is kept by Windows); Triggers: At startup, delay 1 minute; Actions: start the program C:\Pyrite\pyrite.exe, arguments --autostart --unattended, start in C:\Pyrite; Settings: If the task fails, restart every 1 minute, up to 3 times; untick Stop the task if it runs longer than; If the task is already running: do not start a new instance. Do not use Run with highest privileges: the engine does not need it.
Exit codes and what happens
| Code | When | What the task does |
|---|---|---|
0 | The engine was stopped on request (Exit, Windows shutting down). | Nothing: it is not a failure. |
1 | An error: port 8080 is taken by another program; logs\engine.log cannot be opened (the account has no Modify on the folder); the icon or the engine do not start; the engine stops by itself. | “If the task fails, restart” should start it again (up to 3 times, one minute apart): see below. The reason is in logs\engine.log (if the log can be opened). |
3 | There is already a Pyrite running for the same folder, or one answers on the same port. | The new copy gives way: a restart would find the first one again, so after the attempts the task stays as it is. The line in logs\engine.log says which case it was. |
If you end the task (Stop-ScheduledTask, or “End” in the Task Scheduler), the exit code is not chosen by Pyrite: Windows decides it.
To start it without restarting the PC: Start-ScheduledTask -TaskName Pyrite. Stop-ScheduledTask ends the task, but it is not proven that the engine then stops in an orderly way: the engine closes in order only when the program that starts it is asked to close or Windows shuts down, and ending a task usually ends the process at once. So, before stopping it, stop the apps from the console (button Stop in the page of each app) and, if you have just changed something, make a backup from the Backups page; after the restart look at the Overview and at logs\engine.log. An engine started by hand and the task cannot run together on the same folder: a second engine on the same folder does not start (exit code 3 without anybody at the screen).
The limits of the scheduled task
- No icon. There is no icon to look at and no “Exit”. To know if the engine is alive, open
http://SERVER:8080/from another PC (the best check, in any case: do not trust only the state of the task), or readlogs\engine.log(the messages of the engine, 10 MB, the last 3 copies). - Check the restart. After setting up the task, try it: stop the engine's process and occupy port 8080 with another program. Check above all that the task really starts again after an exit code 1: it is not certain that “If the task fails, restart” looks at the exit code of the program and not only at a failed start. If it doesn't start again, there is no automatic restart: you need a check from outside (
http://SERVER:8080/from another PC). - The backups on the NAS need the account of the task to be known to the NAS: with a local account of the PC that the NAS does not know, the copy cannot write (the test of the page says it). See Permissions on the folder.
- Updating works as always (stop the task, replace
pyrite.exe, start the task); the firewall rule is for the path of the file: if the path stays the same, nothing to change. - If the PC is also used by someone who signs in, don't turn on Start with Windows too: a second engine does not start, but it is confusing.
37 /Alpha warnings
- Local network first. Without a certificate the engine works in HTTP and passwords and data travel in clear text inside the network: turn on HTTPS from the Certificates page. From 0.7.5 you can open some apps to the internet (Network rules): do it only with HTTPS on, one app at a time, and only for non-sensitive data. The console never opens from the internet.
- Non-sensitive data only. Don't use it for personal data that need protection, health data, payments or anything critical.
- No warranty. This is an alpha, provided “as is”, to try the product. Data formats and screens may change in the next versions. Keep copies of what matters.
- Apps of several customers on one engine. The fence around the scripts is a defence inside the program, not a wall: do not rely on it alone for scripts written by someone you don't trust (see What an app can do).
- Updating the engine. The engine makes a restore point by itself. For an extra safety net in this alpha, you can also copy the whole folder while the engine is stopped, before replacing
pyrite.exe.
38 /Known limits
These are the things 0.7.7 does not do, or does only in part. They are here so that you know them before you rely on it.
- The console is never reachable from the internet in this version, whatever the settings.
- The engine history is not an absolute guarantee. Whoever has the files of the server and knows how Pyrite works can still rewrite the events. Pyrite is built to notice changes in the file (Check, every night), but it can't promise to notice all of them.
- The logs of the tunnel and of the proxies are confidential data. Whoever reads them in real time and is faster than the browser of the person can use their link to enter an app once. It is an almost theoretical case (the link must be read and used in the few thousandths of a second before the browser of the person arrives): the person sees “This link to open the app is no longer valid” and opens the app again, and the Engine history always gets the event “code used a second time”, with the notice with the two addresses. Someone who reads those logs and also has the permission on the app can send the person a link prepared with the sender's own account, in the 10 minutes at most in which the person opened the app without having signed in to the portal yet: the person sees the page with the sender's name, and for the trick to work must accept a name that is not theirs and press Continue. If they press Leave the Engine history gets an event; if they continue, the notice. If the sender and the person go out to the internet from the same address (the same network) the page doesn't appear.
- Two copies of the same folder on the same server throw each other out of the sign-in, because the copy carries the identifier of the engine with it.
- If the engine can't read its identifier (the file
control\pyrite.jsonis damaged or can't be written at the start), it works with the names of 0.7.4. When the identifier is back, those who signed in in the meantime sign in again once. Nothing is at risk. - The Cloudflare key stays only on this server. If the engine moves to another computer, put it back. Pyrite doesn't ask Let's Encrypt about revocations by itself: if a certificate has to be replaced, press Renew now.
- Let's Encrypt with port 443 makes one certificate for every name (no asterisks), and with a tunnel or a proxy you need the DNS.
- The Windows service account writes only in the folder of Pyrite: for a copy of the backups on another disk of the server, give it the permissions, or use
--localsystem. While the service is installed, the foldercontrol\certificatican't be read by the user of the icon: it is on purpose, and it holds until you remove the service. With the engine on, the service doesn't change the firewall (see The Windows firewall). - An Admin no longer sees in the Overview the names of the portal in the certificate notices, only the names of their own apps.
- The fence around the scripts is not a wall. It greatly reduces what an app's script can do, but it is inside the program: the script runs in the same process as that app's engine, with the same Windows user. The full guarantee for apps of third parties will be one Windows user for each app, in a future version. Until then, apps of different customers on one engine are fine if the scripts are written or checked by whoever runs the engine (see What an app can do).
- Calls of an app to the public address of the server. The profile picture taken from an OAuth2 sign-in and the calls of an app to the public address or public name of this server leave without the engine's mark: they reach the engine like any request from outside. A network address just taken by the server stays unmarked for up to a minute (the network cards are read again every 60 seconds). An app that calls itself by its name from the internet entrance gets “does not exist”. A proxy of yours that runs on the same computer may have the address 127.0.0.1: for the engine its requests are “from this computer”.
- A tunnel or proxy pointed straight at the port of an app (instead of the engine's internet entrance) makes the app read the address of the proxy and not the one of the visitor. The right road is the internet entrance, with whoever stands in front declared in the network rules.
- Another program on the internal port of an app. Whoever takes the internal port of a stopped app can do only one thing: stop the app from starting, and it is seen (see What an app can do). The window in which another program can take the port, from the start of the process to the opening of the port, was measured on one unloaded PC at about 0.2 to 0.3 seconds.
- Two-factor authentication. It does not see who writes the users table without going through the saves of PocketBase (direct SQL, an Owner's SQL console). Whoever holds the server (the registry and the openable key, with the user who runs the engine) can still make a sign-in ticket. The count of wrong codes starts again when the engine restarts.
- Units, and what a person can still see. Whoever manages many units sees, in the history, less rather than more: with 11 units only the people who are in at most 5 units, and so on down. An App Admin still reads, in the history of the app, the old events of a person later moved to another unit. On the native API, a filter on the units field can tell whether a person is also in another unit, if you know the id of that unit. When a page carries the email of an Owner, any person with the same name as the Owner is also shown as “Owner”. Moving an app or a group and giving an access at the very same moment can leave an access across two units: the engine reports it at the start.
- Pages that don't yet say everything. The summary of an uploaded package doesn't say in which unit the app will be born. Moving an app doesn't remove by itself the people who are left with nothing in the starting unit. The person menu of the History reads at most 1000 people.
- Not yet tried with the real thing (a real tunnel, a real Let's Encrypt and Cloudflare, the Windows service on a real server, Windows Server, a split DNS).
39 /For technicians
Commands
They are typed in a command window opened in the folder of the program (in PowerShell type .\pyrite.exe instead of pyrite.exe); with a command after the name, the program writes into that window. Without any command (pyrite.exe alone) it starts as with the double click, with the icon.
| command | what it does |
|---|---|
pyrite.exe serve --http=0.0.0.0:8080 | the engine in the terminal, on the chosen address and port; Ctrl+C stops it cleanly |
pyrite.exe owner reset EMAIL | a temporary password for an Owner, printed once, to be changed at the next sign-in; the other console sessions of that Owner end. With --enable it also enables an Owner who is disabled. Only for Owners |
pyrite.exe owner create EMAIL | creates an Owner with a temporary password, when /setup/ can't be opened; --name "Mary Smith" for the name. If the engine already has an active Owner, repeat the email with --confirm EMAIL. If the folder looks like the incomplete copy of a Pyrite that was already there, the command stops and asks for --new-engine (see Moving Pyrite to another computer). Never an email that is already in the directory (for an existing Owner use owner reset) |
pyrite.exe owner two-factor-off EMAIL | removes two-factor authentication from an Owner (lost phone, engine moved), with the engine running or stopped; the sessions of that Owner end. Only for Owners (see Two-factor authentication) |
pyrite.exe update-restore | with the engine stopped, puts back the restore point of the last engine update (the engine's data, the data and settings of the apps); without --yes it only says what it would do. Then put back the pyrite.exe of before (see Updating from 0.7.5) |
pyrite.exe network status | the network rules in use (file control\pyrite.json). With the engine stopped, network reset goes back to the values of 0.7.4 and network setup asks the two network questions (see Network rules) |
pyrite.exe service install | in a Command Prompt opened as administrator: installs Pyrite as a Windows service; service status says how it is, service uninstall removes it; service install --no-firewall skips the firewall rule (see Pyrite as a Windows service) |
pyrite.exe firewall status | how the Windows firewall is for Pyrite (no administrator rights needed); firewall open and firewall close make and remove the rule for the program (TCP only), in a Command Prompt opened as administrator (see The Windows firewall) |
pyrite.exe certificates off | with the engine stopped, goes back to HTTP when HTTPS is misconfigured (the certificate stays: turn it back on from the console); certificates status says how HTTPS is set (see Emergency exit) |
pyrite.exe import <file> | reads a CSV, Excel (.xlsx, .xls) or JSON file and tells columns and types, without loading anything; options such as -sheet, -separator, -encoding, -header none|titles|preamble, -json (all of them with import -h) |
pyrite.exe tools | the catalog of the engine tools; --md the tools chapter of the agent standard, --json the data, --lang it the Italian texts |
pyrite.exe --help | the list of the commands |
- The
ownercommands work with the engine stopped or running: a running engine reads the change within a few seconds. If the engine is just making a backup or a restore, they ask to try again in a few minutes. - The engine does not include the PocketBase
superusercommand: the engine's PocketBase account is a technical account with a random password that the engine manages by itself, and nobody signs in with it. For the local test of a single app (pyrite.exe worker …) it is still there: see the agent standard. - The program is built not to open windows: that's why cmd and PowerShell don't wait for it when you type it by hand. The prompt comes back at once and the program's messages appear below it, mixed with the prompt; Ctrl+C still stops the engine cleanly. To make them wait as for a normal program: in cmd
start "" /wait /b pyrite.exe serve --http=0.0.0.0:8080; in PowerShellStart-Process -Wait -NoNewWindow .\pyrite.exe -ArgumentList 'serve','--http=0.0.0.0:8080'(servewithout--httplistens only on this computer, on port 8090); inside a.batfile cmd already waits by itself. - The exit code is the real one only when the command is waited for:
%ERRORLEVEL%inside a.batfile or afterstart "" /wait /b; in PowerShell(Start-Process -Wait -NoNewWindow -PassThru .\pyrite.exe -ArgumentList …).ExitCode. - The commands the engine suggests (in the console, on the sign-in page, in the terminal) use the real name of the program file: if you rename
pyrite.exe, they follow. - In the terminal the engine writes
Company portal: …/andEngine console: …/console/; the lineDashboard: …/_/written by PocketBase leads to the console as well. - In Task Manager the processes are: one for the icon, one for the engine, one for each app with a database. Don't end them from there: stop everything with Exit.
- If a list of “Superuser IPs” is set in the PocketBase settings, it stays in force: the console opens only from the computers in the list, and the others get a clear message. Owners see the list under Advanced, with a warning and Empty the list.
- The password-reset email is sent only to active Owners, at most once every 2 minutes for each person (and at most 5 requests every 15 minutes from the same address); the page answers in the same way for every email, so it doesn't tell who is in the directory.
40 /Problems and licenses
- Someone with two-factor authentication can't enter the console any more: the engine was moved or the key file was lost. An Owner removes it with
pyrite.exe owner two-factor-off EMAILand the person turns it on again (see Two-factor authentication). - The update stops and says that a name is already taken: a field called
unitsorunit, or a collection calledorch_unitsororch_roles, belongs to one of your apps. Nothing was changed: see Checks to make first. - An app is “failed” or “unhealthy” and says another program answers on its internal port: see What an app can do.
- The console says it is for Owners and Admins: your account has the User level; ask an Owner.
- After a restart of the engine the console asks to sign in again: it is normal, the sessions are kept only in memory.
- The engine says “Too many sessions are open on the engine: try again in a moment”: too many console sessions or Data panels are open at once (there is a limit for each person and one for the whole engine). Close the ones you don't need (Profile → Console sessions → close all the others) or try again after a minute.
- The console asks for the password again after a few minutes: it closes by itself after the time without use set in Network rules (30 minutes by default), and after 12 hours in any case (see The console closes by itself).
- The page of the first Owner shows a warning about an incomplete copy and does not go on: the registry
control\pb_data\data.dbis missing from a folder that has already been used. If you are moving Pyrite, close the engine and copy again; tick “Yes, it is a new engine” only if it really is new (see Moving Pyrite to another computer). - The box “Windows firewall” shows the command and no button: the button exists only in a few cases, on purpose (see The Windows firewall); give the command on the server as administrator.
- An app doesn't start and says it is waiting for approval: an Owner has to approve it first.
- The engine says the update didn't start: read the message (in the window “Pyrite couldn't start.” that Pyrite shows, with the last lines of the log, and in
logs\engine.log: the console doesn't open). Nothing was changed: another engine running on the same folder, a file that can't be written, or not enough free space on the disk. Fix it and start the engine again. - An app stops working after the update: look at its Status tab and at the events: the console says why and what to do. When the problem is in the app's files (a script, a migration), the engine stops restarting it and tries again by itself when the files change, or when you press Restart. To go back, see Going back to the previous version.
- An app doesn't start and says that its archiving isn't finished: on the Archive page press Finish the archiving on its entry (see The Archive page).
- The sign-up page of an app does not work: the users of the apps are decided by whoever manages Pyrite (see Sign-up to the apps).
- The first-start page says it opens only with an address of the engine, or asks for a code: use the IP address or the name of the computer, and read the code in the window of the engine or in
logs\engine.log(see First start). - The sign-in page of the console says it opens only from some addresses: use one of the allowed addresses (for example the VPN, or the server itself), or ask an Owner to change the list in Network rules (see Sign-in).
- From the internet the browser shows an HTTPS error: the name has no certificate that covers it, or it is not a name Pyrite serves from the internet. See Let's Encrypt, Cloudflare and more certificates.
- Nothing can be seen from the other computers: check that
pyrite.exeis allowed on private networks in the Windows firewall (the permission is for the file: a program file with another name or in another folder needs it again):pyrite.exe firewall statussays how it is, and the box “Windows firewall” in Network rules shows it (see The Windows firewall). Use this computer's IP address or name.
Pyrite includes PocketBase (MIT license, © Gani Georgiev) and other open-source components: their licenses are in THIRD-PARTY-NOTICES.txt. Pyrite is an independent project built on PocketBase; it is not affiliated with or endorsed by PocketBase or its author.