# IceHrm: a self-hostable HR system with a Docker path and a paid extension layer

> IceHrm is an HR management application covering employee records, leave, attendance, timesheets and self-service, deployable in one Docker Compose command and updatable from the dashboard since v36. It is also a commercial product, since extensions are sold and unlocked by linking an installation to the vendor.

**gamonoid/icehrm** — Manage your employees easily with a robust and efficient Human Resource Management System

- Repository: https://github.com/gamonoid/icehrm
- Website: http://icehrm.com
- Stars: 734 · Forks: 428
- Language: JavaScript
- License: NOASSERTION
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/gamonoid-icehrm

## What the HR system actually covers

IceHrm is described in the README as a comprehensive HRM software that enables companies to manage employee information, track attendance, handle leave requests and streamline HR workflows. The feature set breaks into five areas with screenshots attached to each. Core HR management gives centralized employee records covering personal details, job history, qualifications, documents and dependents, alongside a company structure you can browse as a list or as an org chart. Leave management lets employees apply and track leave with their entitlement, pending and approved requests in one place, while managers approve or reject from the same screen; administrators define leave types, the leave period, the work week and public holidays, and can post manual leave adjustments, and a calendar lays the whole team's absences across the month so clashes are visible before approval. Time and attendance covers punch in and out with full attendance history per employee plus an overtime request and approval flow. Projects and timesheets track clients and projects, assign employees, and capture weekly timesheets with a per-project breakdown and an approval step. Every employee also gets a dashboard with leave balances, upcoming holidays and pending requests, plus a searchable staff directory.

## One command to a running instance

The Docker path is the shortest route to a working installation, and the README gives it as three lines:

```bash
git clone https://github.com/gamonoid/icehrm.git
cd icehrm
docker compose up -d --build
```

The README is honest that the build compiles the frontend assets inside the image, so the first run takes a few minutes. When it finishes, the application is at http://localhost:5555, and the credentials are admin / admin, with an explicit instruction to change that password before exposing the installation. The stack is three containers: the application, a MySQL 8 database seeded from docker/init.sql, and a worker for background jobs. Settings and uploads live in named volumes, icehrm-app-data and icehrm-mysql-data, and survive a rebuild. To change the port, base URL or database credentials, the README says to copy docker-prod.env.example to .env first. A Linux VPS deployment is offered as the second option, through an installation guide published on the vendor documentation site, and a separate guide covers setting up a development environment for contributing or extending the code.

## Three containers, and a MySQL port deliberately bound to loopback

The compose file in the repository root is where the operational detail sits, and one decision is worth reading closely. The mysql service publishes its port as 127.0.0.1:${DB_PORT:-9555}:3306, and the file carries a comment explaining why: loopback only, because an unauthenticated MySQL on 0.0.0.0 is reachable by anything on the same network, such as coffee shop wifi or a corporate LAN. The application service publishes ${APP_PORT:-5555}:8080 and waits on the database through a healthcheck that pings mysqladmin every ten seconds with a thirty second start period, and the depends_on block sets the condition to service_healthy with required set to false. The worker is a separate service built from Dockerfile-worker with an EXE_ENV=prod build argument, and it receives the same database environment variables as the application. The comment style in this file is a small but useful signal: the people who wrote it were thinking about the failure mode of exposing a database on a shared network, and they left that reasoning in the repository rather than in a wiki page.

## A PHP and JavaScript stack behind the interface

The repository is bigger than the feature list suggests, and the directory names give a fair picture of the architecture. There are app, core, extensions, web, deployment, tools, updater, test and e2e directories, alongside several Dockerfiles for development, testing, release testing and the worker, a Vagrantfile, a RoboFile.php for PHP tasks, a build.xml, and a phpunit.xml. The JavaScript side is a gulp pipeline: the package manifest points main at gulpfile.js and lists browserify, babel, less, uglify, sourcemaps and a watcher as dev dependencies, with the scripts wired to npm run asset:build:prod in the container build. The production image makes the same split explicit. The builder stage runs on node:18-alpine and installs bash because obfuscate-js.sh uses process substitution, copies the package files, the web assets, app, core, extensions and docker directories, and runs the asset build; it then removes node_modules before the production stage copies anything, because the comment notes that anything left in the build stage ships in the final image. The runtime stage is alpine:3.20 with nginx, php83-fpm and supervisor, and the label identifies the production container as Nginx and PHP-FPM based. The primary language recorded for the repository is JavaScript, but the server side is clearly PHP, which is worth keeping in mind when you look for a developer.

## Self-updating since v36, with a rollback path

From v36, IceHrm updates itself, and this is the most consequential operational fact in the README. Administrators see a banner on the dashboard when a newer release is published, and the updater then downloads it, backs the current version aside before replacing anything, preserves app/config.php, app/data/ and any extensions you installed yourself, and can roll back from the same screen if the application does not come back. The mechanism is reasonable on its face: a backup before replacement, a preserved config and data directory, and a rollback on the same screen where the update was triggered. It also means that your production instance will, by default, offer to replace itself with a new version without a manual release process on your side. The releases behind it are frequent, with v36.0.1 published on 2026-10-01, v36.0.0 on 2026-09-14 and v35.0.1 on 2026-02-12, and the last push to the repository was on 2026-10-18. If your change control process requires a human approving each version, that banner is a decision point you need to own rather than ignore.

## Linking to the vendor is how extensions and updates arrive

The README does not present the self-hosted project as entirely self-contained, and the After Installation section is explicit about the commercial layer. Step one is to connect to IceHrm.com, which links your installation to unlock extensions and receive updates, with a connection guide published on the vendor site. Step two is to install extensions, described as powerful modules for your business needs, through an extension installation guide that lives on the same purchase-oriented documentation site. Elsewhere the README says outright that IceHrm is available as a fully managed service at icehrm.com with no installation or maintenance required, which is the hosted version of the same product. So there are three deployment shapes on offer: self-hosted from this repository, self-hosted and linked to a vendor account for extensions and updates, and fully managed. The commercial weight of that third shape also shows in the licensing. GitHub classifies the repository licence as Other, a custom licence it cannot map to a known identifier, and the LICENSE file at the root is the authoritative text, while the JavaScript package manifest separately declares an ISC licence. Two different licences in one tree is a detail to read rather than assume.

## Where this is the wrong choice

Several limits are visible without going beyond what the repository says. The default credentials are admin / admin, and the README itself warns you to change the password, which means a deployment that skips that step is a deployment with a known public password. The application listens on a port you expose yourself, and while the MySQL port is bound to loopback, the application port is not, so the reverse proxy and TLS story is yours to build and the README does not document one. The feature coverage is HR-adjacent rather than payroll-deep: the README mentions attendance, leave, timesheets and employee records, and says nothing about payroll calculation, tax handling or statutory reporting, so a buyer expecting those should look elsewhere. Extensions, which the README positions as the way to expand for your business needs, are sold through the vendor rather than developed in the open, which is the opposite trade from what the open repository offers for the core. For an organisation that needs the whole surface to be auditable and self-hosted without a vendor relationship, the extension model and the self-update banner are the two places to push back.

## Conclusion

IceHrm suits a small or mid-sized company that wants leave, attendance and employee records under its own control, has a Docker host or a Linux VPS, and can accept a PHP and MySQL stack that the project maintains through its own release train. It does not suit a team that needs a verified restore path or a fully offline installation, because linking an installation to the vendor account is how extensions and updates are unlocked, and it does not suit anyone who wants the feature set frozen, since the application is on version 36 with a self-updating mechanism added in v36. Verify first that the update banner in your dashboard is one you want an application to act on, then check that docker/init.sql seeds the MySQL instance you expect, and confirm the port binding of the mysql service stays on loopback before you put the stack on a shared network.

## FAQ

### How do I deploy IceHrm with Docker?

The README gives three commands: git clone the repository, cd icehrm, then docker compose up -d --build. The first run takes a few minutes because the build compiles the frontend assets inside the image, and the application then answers on http://localhost:5555 with admin / admin credentials.

### What containers does the IceHrm Docker stack run?

Three: the application, a MySQL 8 database seeded from docker/init.sql, and a worker for background jobs. Settings and uploads live in named volumes icehrm-app-data and icehrm-mysql-data.

### How do I change the port, base URL or database credentials?

The README says to copy docker-prod.env.example to .env first. The compose file reads APP_PORT, APP_BASE_URL, DB_HOST, DB_NAME, DB_USER and DB_PASSWORD from that file, with defaults such as 5555 for the application port and 9555 for the loopback-bound MySQL port.

### Does IceHrm update itself?

From v36 it does. A banner appears on the dashboard when a newer release is published, and the updater backs the current version aside before replacing anything, preserves app/config.php, app/data/ and your own extensions, and can roll back from the same screen.

### Is IceHrm free to self-host without a vendor account?

The repository is self-hostable from the Docker Compose steps in the README, and the README also offers a fully managed service at icehrm.com. Linking an installation to the vendor account is what unlocks extensions and receives updates, and extensions are sold through the vendor.

## Sources

- [gamonoid/icehrm on GitHub](https://github.com/gamonoid/icehrm)
- [Issues](https://github.com/gamonoid/icehrm/issues)
- [Project website](http://icehrm.com)
- [README](https://github.com/gamonoid/icehrm/blob/master/README.md)
- [Releases](https://github.com/gamonoid/icehrm/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/gamonoid-icehrm
