IronCalc is an open-source spreadsheet that replaces Excel with a private, in-browser calculation grid running locally without subscription fees.
Microsoft Excel requires recurring Microsoft 365 subscription fees, while cloud alternatives lock advanced file sharing behind per-user monthly bills. IronCalc eliminates ongoing software costs by providing an open spreadsheet environment that opens, edits, and recalculates workbooks directly in your browser. All calculations run on your local device without user registrations, paid upgrades, or external telemetry.
Microsoft Excel remains the dominant office spreadsheet, but accessing it requires buying a desktop license or paying monthly per-user fees to Microsoft 365. Google Sheets avoids upfront fees but demands a persistent Google account and routes data through corporate servers. IronCalc takes a different path: it offers a standalone calculation grid that loads in any browser or runs inside a local Docker container with no licenses to purchase, no tier limits, and no recurring invoices.
The cost savings come with clear functional trade-offs. IronCalc covers the core calculation mechanics that people rely on daily, including over 300 formula functions, multi-sheet workbooks, cell formatting, and direct .xlsx import and export. However, it does not match Excel's enterprise depth. Users trading commercial suites for IronCalc give up visual charting, pivot tables, and automation macros in exchange for an unencumbered, private grid that costs nothing to operate.
.xlsx compatibility: workbooks created in other spreadsheet programs open cleanly and export back to the universal format, preventing file lock-in.Can IronCalc open and edit standard Excel files?
Yes. IronCalc imports and exports standard .xlsx files, allowing you to edit numbers and formulas without altering the underlying file structure.
IronCalc vs Microsoft Excel — which should I choose? Choose Microsoft Excel if your workflow requires complex pivot tables, visual charts, or automation macros; choose IronCalc if you need a cost-free, private spreadsheet for standard table calculations without recurring subscriptions.
Is IronCalc free to use? Yes. You can use the hosted browser version without paying fees, or deploy the self-hosted container on your own hardware at zero software cost.
IronCalc is an excellent fit for people who want to crunch numbers in standard spreadsheets without paying monthly subscription fees, but it cannot yet replace full office suites for users dependent on visual charts or pivot tables. Because the project remains under active development with code pushes in September 2026 and carries an Apache-2.0 license that permits freely running and sharing the software, it stands as a dependable, budget-friendly alternative for everyday calculation tasks.
We started this exact setup from scratch in a clean Linux machine on Nov 3, 2026 and checked it through IronCalc 's own API: every check passed. Recipes are re-checked regularly and removed if they stop working.
mkdir -p ironcalc && cd ironcalc
curl -fsSL https://open-source.store/tools/ironcalc/compose.yml -o compose.ymltouch .envdocker compose up -dservices:
server:
image: ghcr.io/ironcalc/ironcalc-server:0.9.1
restart: always
caddy:
image: ghcr.io/ironcalc/ironcalc-caddy:0.9.1
ports:
- "127.0.0.1:2080:2080"
depends_on:
- server
restart: always
healthcheck:
test: ["CMD-SHELL", "wget -q -O /dev/null http://127.0.0.1:2080/ || exit 1"]
interval: 5s
timeout: 5s
retries: 5
Lint, codegen, breaking-change checks and dependency management in one Git-native CLI. Open source, no registry lock-in.
Show that IronCalc is listed as an open-source alternative. Paste into your README:
Ubuntu 24.04 · Apple container, Docker 29.1.3, Compose 2.40.3+ds1-0ubuntu1~24.04.1. Images pulled in 9 s: ghcr.io/ironcalc/ironcalc-server:0.9.1, ghcr.io/ironcalc/ironcalc-caddy:0.9.1.
Based on the upstream setup. Official compose. Build contexts removed to use published ghcr.io multi-arch images; caddy port 2080 bound to 127.0.0.1 because IronCalc has no built-in authentication and exposes unauthenticated write and model enumeration endpoints.
caddy-1 | 2026-11-03T05:30:54.100814630Z {"level":"info","ts":1793683854.100336,"msg":"maxprocs: Leaving GOMAXPROCS=2: CPU quota undefined"}
caddy-1 | 2026-11-03T05:30:54.100828505Z {"level":"info","ts":1793683854.1003463,"msg":"GOMEMLIMIT is updated","GOMEMLIMIT":3820057804,"previous":9223372036854775807}
caddy-1 | 2026-11-03T05:30:54.100829713Z {"level":"info","ts":1793683854.1003482,"msg":"using config from file","file":"/etc/caddy/Caddyfile"}
caddy-1 | 2026-11-03T05:30:54.100830463Z {"level":"info","ts":1793683854.100351,"msg":"adapted config to JSON","adapter":"caddyfile"}
caddy-1 | 2026-11-03T05:30:54.100831213Z {"level":"warn","ts":1793683854.1003518,"msg":"Caddyfile input is not formatted; run 'caddy fmt --overwrite' to fix inconsistencies","adapter":"caddyfile","file":"/etc/caddy/Caddyfile","line":2}
caddy-1 | 2026-11-03T05:30:54.100832505Z {"level":"info","ts":1793683854.1006014,"logger":"admin","msg":"admin endpoint started","address":"localhost:2019","enforce_origin":false,"origins":["//localhost:2019","//[::1]:2019","//127.0.0.1:2019"]}
caddy-1 | 2026-11-03T05:30:54.100990422Z {"level":"info","ts":1793683854.1009712,"logger":"tls.cache.maintenance","msg":"started background certificate maintenance","cache":"0x2f90902ba780"}
caddy-1 | 2026-11-03T05:30:54.101087380Z {"level":"warn","ts":1793683854.1010282,"logger":"http","msg":"HTTP/2 skipped because it requires TLS","network":"tcp","addr":":2080"}
caddy-1 | 2026-11-03T05:30:54.101089797Z {"level":"warn","ts":1793683854.1010327,"logger":"http","msg":"HTTP/3 skipped because it requires TLS","network":"tcp","addr":":2080"}
caddy-1 | 2026-11-03T05:30:54.101090672Z {"level":"info","ts":1793683854.1010337,"logger":"http.log","msg":"server running","name":"srv0","protocols":["h1","h2","h3"]}
caddy-1 | 2026-11-03T05:30:54.101354213Z {"level":"info","ts":1793683854.1013365,"msg":"autosaved config (load with --resume flag)","file":"/config/caddy/autosave.json"}
caddy-1 | 2026-11-03T05:30:54.101357380Z {"level":"info","ts":1793683854.1013389,"msg":"serving initial configuration"}
caddy-1 | 2026-11-03T05:30:54.102175297Z {"level":"info","ts":1793683854.1021416,"logger":"tls","msg":"cleaning storage unit","storage":"FileStorage:/data/caddy"}
caddy-1 | 2026-11-03T05:30:54.102633797Z {"level":"info","ts":1793683854.1026032,"logger":"tls","msg":"finished cleaning storage units"}
caddy-1 | 2026-11-03T05:30:54.194816630Z {"level":"info","ts":1793683854.1947248,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.1","remote_port":"58236","client_ip":"172.18.0.1","proto":"HTTP/1.1","method":"GET","host":"127.0.0.1:2080","uri":"/","headers":{"Connection":["close"],"Accept-Encoding":["identity"],"User-Agent":["Python-urllib/3.12"]}},"bytes_read":0,"user_id":"","duration":0.00099775,"size":1027,"status":200,"resp_headers":{"Content-Type":["text/html; charset=utf-8"],"Last-Modified":["Wed, 21 Oct 2026 13:47:20 GMT"],"Accept-Ranges":["bytes"],"Content-Length":["1027"],"Server":["Caddy"],"Vary":["Accept-Encoding"],"Etag":["\"dmak9ziued4w-sj\""]}}
caddy-1 | 2026-11-03T05:30:54.195150755Z {"level":"info","ts":1793683854.1951072,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.1","remote_port":"58246","client_ip":"172.18.0.1","proto":"HTTP/1.1","method":"GET","host":"127.0.0.1:2080","uri":"/","headers":{"Accept-Encoding":["identity"],"User-Agent":["Python-urllib/3.12"],"Connection":["close"]}},"bytes_read":0,"user_id":"","duration":0.00006825,"size":1027,"status":200,"resp_headers":{"Server":["Caddy"],"Vary":["Accept-Encoding"],"Etag":["\"dmak9ziued4w-sj\""],"Content-Type":["text/html; charset=utf-8"],"Last-Modified":["Wed, 21 Oct 2026 13:47:20 GMT"],"Accept-Ranges":["bytes"],"Content-Length":["1027"]}}
caddy-1 | 2026-11-03T05:30:54.196253088Z {"level":"info","ts":1793683854.196196,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.1","remote_port":"58254","client_ip":"172.18.0.1","proto":"HTTP/1.1","method":"GET","host":"127.0.0.1:2080","uri":"/api/list","headers":{"Accept-Encoding":["identity"],"User-Agent":["Python-urllib/3.12"],"Connection":["close"]}},"bytes_read":0,"user_id":"","duration":0.000823666,"size":0,"status":200,"resp_headers":{"X-Content-Type-Options":["nosniff"],"Content-Length":["0"],"Date":["Tue, 03 Nov 2026 05:30:54 GMT"],"Content-Type":["text/plain; charset=utf-8"],"Via":["1.1 Caddy"],"Server":["Rocket"],"X-Frame-Options":["SAMEORIGIN"],"Permissions-Policy":["interest-cohort=()"]}}
caddy-1 | 2026-11-03T05:30:54.197754172Z {"level":"info","ts":1793683854.1976984,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.1","remote_port":"58260","client_ip":"172.18.0.1","proto":"HTTP/1.1","method":"POST","host":"127.0.0.1:2080","uri":"/api/share","headers":{"Content-Length":["32"],"User-Agent":["Python-urllib/3.12"],"Content-Type":["application/json"],"Connection":["close"],"Accept-Encoding":["identity"]}},"bytes_read":32,"user_id":"","duration":0.001283417,"size":17,"status":200,"resp_headers":{"Via":["1.1 Caddy"],"Content-Type":["text/plain; charset=utf-8"],"Server":["Rocket"],"X-Frame-Options":["SAMEORIGIN"],"Permissions-Policy":["interest-cohort=()"],"X-Content-Type-Options":["nosniff"],"Content-Length":["17"],"Date":["Tue, 03 Nov 2026 05:30:54 GMT"]}}
caddy-1 | 2026-11-03T05:30:54.198135547Z {"level":"info","ts":1793683854.1980855,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.1","remote_port":"58276","client_ip":"172.18.0.1","proto":"HTTP/1.1","method":"GET","host":"127.0.0.1:2080","uri":"/api/list","headers":{"Accept-Encoding":["identity"],"User-Agent":["Python-urllib/3.12"],"Connection":["close"]}},"bytes_read":0,"user_id":"","duration":0.000143209,"size":17,"status":200,"resp_headers":{"Server":["Rocket"],"X-Frame-Options":["SAMEORIGIN"],"Via":["1.1 Caddy"],"Permissions-Policy":["interest-cohort=()"],"X-Content-Type-Options":["nosniff"],"Content-Length":["17"],"Date":["Tue, 03 Nov 2026 05:30:54 GMT"],"Content-Type":["text/plain; charset=utf-8"]}}
caddy-1 | 2026-11-03T05:30:54.198437213Z {"level":"info","ts":1793683854.1983953,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.1","remote_port":"58284","client_ip":"172.18.0.1","proto":"HTTP/1.1","method":"GET","host":"127.0.0.1:2080","uri":"/models/invoice.ic","headers":{"Connection":["close"],"Accept-Encoding":["identity"],"User-Agent":["Python-urllib/3.12"]}},"bytes_read":0,"user_id":"","duration":0.000086584,"size":4610,"status":200,"resp_headers":{"Etag":["\"dmak9zzdru2o-3k2\""],"Content-Type":[],"Last-Modified":["Wed, 21 Oct 2026 13:47:21 GMT"],"Accept-Ranges":["bytes"],"Content-Length":["4610"],"Server":["Caddy"],"Vary":["Accept-Encoding"]}}
server-1 | 2026-11-03T05:30:54.034929922Z Rocket has launched from http://0.0.0.0:8000
server-1 | 2026-11-03T05:30:54.196149838Z Model list: '[]'
server-1 | 2026-11-03T05:30:54.196583130Z start share
server-1 | 2026-11-03T05:30:54.197760380Z done share: 'aNEav-KrhgP-miiT1'
server-1 | 2026-11-03T05:30:54.198143297Z Model list: '["aNEav-KrhgP-miiT1"]'
caddy-1 | 2026-11-03T05:30:59.148408174Z {"level":"info","ts":1793683859.1483157,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"127.0.0.1","remote_port":"60306","client_ip":"127.0.0.1","proto":"HTTP/1.1","method":"GET","host":"127.0.0.1:2080","uri":"/","headers":{"Connection":["close"],"User-Agent":["Wget"],"Accept":["*/*"]}},"bytes_read":0,"user_id":"","duration":0.00028325,"size":1027,"status":200,"resp_headers":{"Server":["Caddy"],"Vary":["Accept-Encoding"],"Etag":["\"dmak9ziued4w-sj\""],"Content-Type":["text/html; charset=utf-8"],"Last-Modified":["Wed, 21 Oct 2026 13:47:20 GMT"],"Accept-Ranges":["bytes"],"Content-Length":["1027"]}}
caddy-1 | 2026-11-03T05:31:04.188388510Z {"level":"info","ts":1793683864.1882975,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"127.0.0.1","remote_port":"39912","client_ip":"127.0.0.1","proto":"HTTP/1.1","method":"GET","host":"127.0.0.1:2080","uri":"/","headers":{"Accept":["*/*"],"Connection":["close"],"User-Agent":["Wget"]}},"bytes_read":0,"user_id":"","duration":0.000236375,"size":1027,"status":200,"resp_headers":{"Content-Type":["text/html; charset=utf-8"],"Last-Modified":["Wed, 21 Oct 2026 13:47:20 GMT"],"Accept-Ranges":["bytes"],"Content-Length":["1027"],"Server":["Caddy"],"Vary":["Accept-Encoding"],"Etag":["\"dmak9ziued4w-sj\""]}}