GROWI
Overview
GROWI is an open-source team wiki and knowledge base. It stores everything as Markdown pages in a navigable page tree, and supports real-time collaborative editing, diagrams and math, comments, tags and a full revision history.
This image runs GROWI 7.5.6 on Ubuntu 24.04 LTS. GROWI is built from source and run from /opt/growi on the Node.js 24 runtime. An unprivileged growi system account runs it under a systemd service that starts it on boot and restarts it on failure. A local MongoDB 8.0 Community database holds all pages and attachments.
GROWI listens on the loopback address 127.0.0.1:3000 by design and is never exposed directly. nginx is installed as a reverse proxy on port 80 and forwards every request to GROWI, so visitors reach the wiki on the standard HTTP port. Full-text search through Elasticsearch or OpenSearch is optional and is not bundled. The image ships as a self-contained single node, and you can attach a search cluster later.
What you get:
- GROWI 7.5.6 built from source and run by systemd as the unprivileged
growiuser - The GROWI web UI on
:80, through an nginx reverse proxy to127.0.0.1:3000 - A per-VM
adminaccount whose password is generated on first boot and recorded in a root-only file - MongoDB 8.0 Community, bound to loopback with a per-VM credential, with its data directory on a dedicated Azure data disk at
/var/lib/growi - Secure-by-default authentication: self-registration is set to Closed, so the wiki is not world-writable
mongod.service,growi.serviceandnginx.serviceas enabled, active systemd units- An unauthenticated
/healthzendpoint for Azure Load Balancer health probes - 24/7 SecureAnyCloud support
Prerequisites
You need an active Azure subscription, an SSH key pair, and a VNet with a subnet in the target region.
Standard_B2s (2 vCPU / 4 GiB RAM) is a sensible starting size. Choose a larger size for bigger teams and heavier editing.
In the network security group (NSG), allow inbound 22/tcp from your management network and 80/tcp for the wiki. GROWI serves plain HTTP on port 80. For production, terminate TLS in front of it with your own domain and set APP_SITE_URL accordingly.
Step 1 - Deploy from the Azure Marketplace
Sign in to the Azure Portal, choose Create a resource, search the Marketplace for GROWI by SecureAnyCloud, and select Create.
On the Basics tab, pick your subscription, resource group, region and size. Under Administrator account, choose SSH public key and paste your key. Under Inbound port rules, allow SSH (22) and HTTP (80).
Review the dedicated data disk on the Disks tab, then select Review + create and Create.
Step 2 - Deploy from the Azure CLI
Accept the Marketplace terms, create the VM and open port 80:
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:growi-ubuntu-24-04:default:latest
az vm create \
--resource-group <your-rg> \
--name growi \
--image sac1647283583153:growi-ubuntu-24-04:default:latest \
--size Standard_B2s \
--admin-username azureuser \
--ssh-key-values ~/.ssh/id_ed25519.pub \
--vnet-name <your-vnet> --subnet <your-subnet> \
--public-ip-sku Standard
az vm open-port --resource-group <your-rg> --name growi --port 80 --priority 1010Step 3 - Connect to your VM
Connect over SSH as azureuser:
ssh azureuser@<vm-public-ip>Step 4 - Confirm the services are running
nginx serves GROWI on port 80 and reverse-proxies to the Node.js app on 127.0.0.1:3000. The app talks to MongoDB on 127.0.0.1:27017. Confirm that the services are active and the ports are listening:
systemctl is-active mongod growi nginx growi-firstboot
sudo ss -tlnp | grep -E ':80 |:3000 |:27017 'Expected output:
active active active active LISTEN 0 511 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=...)) LISTEN 0 4096 127.0.0.1:27017 0.0.0.0:* users:(("mongod",pid=...)) LISTEN 0 511 *:3000 *:* users:(("MainThread",pid=...))Step 5 - Retrieve your admin password
On the first boot of every VM, growi-firstboot.service generates a unique administrator password, a unique MongoDB credential and a unique application secret (PASSWORD_SEED). It writes them, together with the admin username and the wiki URL, into a root-only file. Confirm that the file exists and is root-only:
sudo ls -l /root/growi-credentials.txtExpected output:
-rw------- 1 root root ... /root/growi-credentials.txtTo get your admin password, read the file with sudo cat /root/growi-credentials.txt. It contains GROWI_ADMIN_USER, GROWI_ADMIN_PASSWORD, MONGO_PASSWORD and PASSWORD_SEED, all unique to this VM.
Step 6 - Confirm the stack and health endpoint
nginx serves an unauthenticated /healthz endpoint for load balancer probes. Confirm the Node.js and MongoDB versions, and check that the wiki responds:
node -v mongod --version | head -1 curl -sI http://127.0.0.1/healthz | head -1 curl -s http://127.0.0.1/login | grep -o '<title>[^<]*</title>'Expected output:
v24.18.0 db version v8.0.26 HTTP/1.1 200 OK <title>GROWI</title>Step 7 - Sign in to the wiki
Browse to http://<vm-public-ip>/. GROWI redirects you to the sign-in page. Enter admin and the password from Step 5.
Step 8 - Explore the top page and page tree
After you sign in, the Welcome to GROWI top page opens. The left sidebar shows the Page Tree, a hierarchical view of every page, including the seeded /Sandbox examples. The right sidebar lists the page contents.
From here you can create new pages, search, tag and organise your knowledge base.
Step 9 - Browse and edit Markdown pages
Open a page from the tree, for example /Sandbox/Markdown, to see GROWI's rendered Markdown: alerts, code blocks, tables, task lists, footnotes and more.
Click Edit (top right) to open the collaborative editor. You write Markdown on the left and see a live preview on the right. Several people can edit the same page at once.
Step 10 - Manage users and keep the wiki private
Open Admin, then User Management. The image ships with a single active admin user and self-registration set to Closed. Nobody can sign up on their own, so the wiki is not world-writable by default.
Invite teammates from this page. To allow approval-based or open sign-up instead, change the registration mode under Security Settings.
Step 11 - Confirm wiki data lives on the dedicated disk
All MongoDB data lives under /var/lib/growi. That includes every page, revision, comment and attachment (stored in GridFS). The path is a dedicated Azure data disk, captured into the image and re-provisioned on every VM:
df -h /var/lib/growi | tail -1 findmnt -no SOURCE,TARGET,FSTYPE /var/lib/growi
sudo ls /var/lib/growi/mongodbExpected output (the data-disk device name may vary between VMs):
/dev/sdX 30G ... /var/lib/growi /dev/sdX /var/lib/growi ext4 WiredTiger WiredTiger.lock WiredTiger.turtle WiredTiger.wt _mdb_catalog.wt ...Maintenance
- Back up your wiki. Everything GROWI stores lives in MongoDB's data files under
/var/lib/growi. Snapshot the data disk, or usemongodump/mongorestorefor logical backups. - Add teammates. Sign in as admin, open Admin, then User Management, and invite users. Registration is Closed by default. Change it under Security Settings if you prefer approval-based or open sign-up.
- Rotate credentials. The admin, MongoDB and app secrets live in
/opt/growi/apps/app/.env.localand/root/growi-credentials.txt. Update them, then runsudo systemctl restart growito apply the change. - Add full-text search. Attach an OpenSearch or Elasticsearch cluster and set
ELASTICSEARCH_URIin/opt/growi/apps/app/.env.local. Restart GROWI to enable full-text search across all pages. - Apply security updates. Unattended security upgrades are enabled, so the OS keeps itself patched. Reboot when a new kernel is installed.
- Use TLS. For production, front GROWI with your own domain and a TLS-terminating reverse proxy or Azure Application Gateway. Set
APP_SITE_URLto yourhttps://URL.
Support
SecureAnyCloud provides 24/7/365 expert technical support for this image. Contact sales@secureanycloud.com.
GROWI is licensed under the MIT License. SecureAnyCloud provides this image, and additional charges apply for build, maintenance and 24/7 support.
Deploy on Azure
Launch GROWI on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.
View this image
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com
Overview
GROWI is an open-source team wiki and knowledge base. Pages are written in Markdown with live preview, edited collaboratively in real time, and organised into a hierarchical page tree with revision history, comments, tags and attachments.
The stack runs in three tiers on one instance. A browser reaches nginx on port 80, nginx proxies to the GROWI Node.js application on port 3000, and the application stores everything in a local MongoDB 8.0 instance on port 27017. MongoDB binds to the loopback interface only and runs with authorization enabled, using a credential unique to your instance.
What you get:
- Automatic installation on the first boot of every instance, so no browser setup wizard is left exposed for the first visitor to claim
- An administrator account with a password unique to that instance, written to
/root/growi-credentials.txtwith mode 0600, alongside a freshly generated MongoDB password and password-hashing seed - Self-registration locked closed, so the wiki is never world-writable
- Two dedicated EBS volumes mounted by filesystem UUID: the MongoDB data directory at
/var/lib/growi, which holds pages, revisions and attachments, and the GROWI application at/opt/growi - Both volumes are independently resizable and separate from the operating system disk
Prerequisites
Before you deploy this image you need:
- An Amazon Web Services account where you can launch EC2 instances
- IAM permissions to launch instances, create security groups, and subscribe to AWS Marketplace products
- An EC2 key pair in the target Region for SSH access to the instance
- A VPC and subnet in the target Region, with a security group allowing inbound port 22 from your management network and inbound ports 80 and 443 from the networks your users will reach the wiki on
- The AWS CLI (version 2) installed locally if you plan to deploy from the command line
Port 3000 needs no inbound rule. nginx reaches the application over the instance's own loopback interface, so leave port 3000 closed in your security group.
Launch the Instance from the AWS Marketplace
Sign in to the AWS Management Console, open the EC2 service, and select Launch instance. Under Application and OS Images, choose AWS Marketplace AMIs and search for GROWI. Select the SecureAnyCloud listing, choose Select, then choose Continue on the subscription summary.
Pick an instance type of m5.large or larger. Choose your EC2 key pair under Key pair (login). Under Network settings select your VPC and subnet, and either create or select a security group that allows inbound port 22 from your management network and inbound ports 80 and 443 from the networks your users use. Leave the root volume and the two attached data volumes at their default sizes or larger.
Select Launch instance. First-boot initialisation takes approximately one to two minutes after the instance state becomes Running. During that time GROWI generates the per-instance secrets, runs its database migrations, creates the administrator account and starts serving.
Launch the Instance from the AWS CLI
Launch an instance from the SecureAnyCloud GROWI Marketplace AMI into an existing subnet and security group. Replace <ami-id> with the AMI ID shown on the Marketplace listing, <key-name> with your EC2 key pair name, <subnet-id> with your subnet ID, and <security-group-id> with a security group that opens ports 22, 80 and 443 as described above.
aws ec2 run-instances \
--image-id <ami-id> \
--instance-type m5.large \
--key-name <key-name> \
--subnet-id <subnet-id> \
--security-group-ids <security-group-id> \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=growi-01}]'The command prints a JSON document on success. Note the instance ID, then retrieve its public address once it is running with aws ec2 describe-instances --instance-ids <instance-id> --query "Reservations[].Instances[].PublicIpAddress" --output text.
Connecting to Your Instance
Connect over SSH with the key pair you selected and the public IP address from Step 2. The SSH login user depends on the operating system of the AMI variant you launched:
- GROWI 7.5.6 on Ubuntu 24.04: SSH login user ubuntu
Confirm the three services that make up the appliance are running:
sudo systemctl is-active mongod.service growi.service nginx.serviceAll three report active:
active active activeConfirm the versions of the components that are installed:
node -v mongod --version | head -1 nginx -v 2>&1
node -p "require('/opt/growi/apps/app/package.json').version"v24.18.0 db version v8.0.26 nginx version: nginx/1.24.0 (Ubuntu) 7.5.6Retrieve the Administrator Login
Every instance generates its own administrator password on first boot. Read the credentials file, which is readable only by root:
sudo ls -l /root/growi-credentials.txt
sudo grep -E '^(GROWI_URL|GROWI_ADMIN_USER)=' /root/growi-credentials.txt-rw------- 1 root root 612 Jul 21 08:06 /root/growi-credentials.txt GROWI_URL=http://203.0.113.10/ GROWI_ADMIN_USER=adminPrint the administrator password when you are ready to sign in, with sudo grep '^GROWI_ADMIN_PASSWORD=' /root/growi-credentials.txt | cut -d= -f2-. Run it only when you are about to use the value, and avoid leaving it in your shell history or terminal scrollback.
The file also records the MongoDB password and the password hashing seed for this instance. Treat the whole file as a secret, and store the administrator password in your password manager. Changing the hashing seed after the fact invalidates every existing password, so leave it alone.
Confirm the Wiki Is Serving
nginx publishes an unauthenticated health endpoint that returns 200 as soon as the appliance is ready. It is a static nginx response and is suitable as the health check for an Application Load Balancer target group.
curl -s -o /dev/null -w 'healthz: HTTP %{http_code}\n' http://127.0.0.1/healthz
curl -s -o /dev/null -w 'login: HTTP %{http_code}\n' http://127.0.0.1/loginhealthz: HTTP 200 login: HTTP 200Confirm which ports are listening. nginx serves on port 80, the GROWI application answers on port 3000, and MongoDB is bound to the loopback address only:
ss -ltn | grep -E ':80 |:3000 |:27017 'LISTEN 0 4096 127.0.0.1:27017 0.0.0.0:* LISTEN 0 511 0.0.0.0:80 0.0.0.0:* LISTEN 0 511 *:3000 *:* LISTEN 0 511 [::]:80 [::]:*Because the application listens on all interfaces on port 3000, keep port 3000 out of your security group. Browsers should always arrive through nginx on port 80 or 443.
Finally, prove the administrator login works end to end against GROWI's own authentication API. This reads the password out of the credentials file into a shell variable, so the password is never printed:
PW=$(sudo grep '^GROWI_ADMIN_PASSWORD=' /root/growi-credentials.txt | cut -d= -f2-)
curl -s -o /dev/null -w 'login round trip: HTTP %{http_code}\n' \
-X POST http://127.0.0.1/_api/v3/login \
-H 'Content-Type: application/json' \
-d "$(printf '{"loginForm":{"username":"admin","password":"%s"}}' "$PW")"login round trip: HTTP 200Sign In
Browse to http://<instance-public-ip>/ in a browser. GROWI redirects unauthenticated visitors to the sign-in page.
Enter the username admin and the password from Step 4, then select Sign in. GROWI opens the top page of the wiki, with the page tree on the left, the rendered page in the centre and the table of contents on the right.
The image ships with GROWI's own welcome content and a Sandbox section, which together are a working tour of the Markdown syntax the editor supports. They are ordinary pages, so delete or rewrite them once your own content is in place.
Create and Edit Pages
Select the pencil icon at the top of the left sidebar to create a page, or Edit at the top right to edit the page you are viewing. The editor is a split view: Markdown source on the left, live rendered preview on the right.
Pages are addressed by path, and the path defines the tree. Creating /engineering/runbooks/database-failover places that page under /engineering/runbooks, creating the intermediate levels if they do not exist, so the structure of your wiki is simply the structure of its page names. Select Update to save. Every save is a revision, and the history is reachable from the page menu at the top right.
Attachments are stored in MongoDB GridFS, on the same dedicated data volume as your page content, so a snapshot of that volume captures both together.
Administration
Open http://<instance-public-ip>/admin as the administrator to reach the wiki management area, which covers app settings, security, user and group management, Markdown behaviour, appearance, plugins and full-text search.
The Wiki Management Homepage confirms the running versions and the environment the appliance was configured with.
Self-registration is set to Closed on this image. This is deliberate and differs from GROWI's upstream default of Open. An open wiki on a public address lets any visitor create an account, so the image locks registration closed on first boot.
Add colleagues from User Management, where you can also grant another account administrator access. If you want open registration, change it under Security Settings, and consider first who can reach the instance.
The Data Volumes
The database and the application each sit on their own EBS volume, separate from the operating system disk:
df -hT /var/lib/growi /opt/growiFilesystem Type Size Used Avail Use% Mounted on /dev/nvme1n1 ext4 20G 204M 19G 2% /var/lib/growi /dev/nvme2n1 ext4 30G 2.6G 26G 10% /opt/growiBoth are mounted from /etc/fstab by filesystem UUID with the nofail option, so the layout survives reboots and relaunches and the instance still boots if a volume is ever detached:
grep growi /etc/fstabUUID=92d54306-51f1-46e7-ac2c-eac9377c0453 /var/lib/growi ext4 defaults,nofail 0 2 UUID=3b8f0584-2199-4d99-a694-14a191b8b63e /opt/growi ext4 defaults,nofail 0 2To grow the wiki's storage, modify the /var/lib/growi volume in the EC2 console or with aws ec2 modify-volume, then extend the filesystem on the instance with sudo resize2fs /dev/nvme1n1. Both operations are online and need no downtime.
Enable HTTPS
Serve the wiki over TLS before putting real content into it. Point a DNS name at the instance, then either terminate TLS at an Application Load Balancer in front of the instance, or issue a certificate on the instance itself with Let's Encrypt. For the second approach, open port 443 in your security group and run certbot against the nginx site the image installs at /etc/nginx/sites-available/sac-growi:
sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d <your-domain> -m <your-email> --agree-tos --no-eff-emailAfter TLS is in place, update the site URL GROWI advertises in links and notifications. Set APP_SITE_URL to the HTTPS address in /opt/growi/apps/app/.env.local and restart the application:
sudo systemctl restart growi.serviceAdd Full-Text Search
The image is deliberately single-node, so GROWI's optional Elasticsearch or OpenSearch backend is not installed. Page browsing, the page tree and the table of contents all work without it. A search across the full text of every page does not.
To add it, stand up an Amazon OpenSearch Service domain reachable from the instance, add ELASTICSEARCH_URI to /opt/growi/apps/app/.env.local pointing at that domain, restart growi.service, then build the index from Full Text Search Management in the administration area.
Backup and Maintenance
Everything that matters lives in MongoDB on /var/lib/growi, so there are two sound backup strategies and you should pick one.
The simplest is an EBS snapshot schedule on the /var/lib/growi volume, managed with Amazon Data Lifecycle Manager. This captures pages, revisions and attachments together and restores as a volume.
The alternative is a logical dump with mongodump, using the per-instance MongoDB credential from /root/growi-credentials.txt and writing to a directory you then copy to Amazon S3:
MPW=$(sudo grep '^MONGO_PASSWORD=' /root/growi-credentials.txt | cut -d= -f2-) sudo mongodump --uri "mongodb://growi:$MPW@127.0.0.1:27017/growi?authSource=growi" --out <backup-dir>Apply operating system updates on your normal schedule with sudo apt-get update && sudo apt-get -y dist-upgrade, and reboot when the kernel changes. The three services start in the right order automatically, so no manual intervention is needed after a reboot.
To review what the application is doing, read its journal:
sudo journalctl -u growi.service -n 20 --no-pagerSupport
This image is supported by SecureAnyCloud. Email sales@secureanycloud.com with your instance ID and AWS Region for help with deployment and sizing, MongoDB administration and backup, TLS termination, attaching OpenSearch for full-text search, GROWI upgrades and troubleshooting.
GROWI is a trademark of its respective owner. All product and company names are trademarks or registered trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.
Deploy on AWS
Launch GROWI on AWS with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com