Skip to content
Documentation

Everything you need to run Inkwell.

Guides, configuration reference, and deployment recipes — all in one place. Inkwell is simple by design; the docs stay short by policy.

Use Ctrl+F to search within this page

Overview

Inkwell is a free, open-source, self-hosted blogging platform built on .NET 10. It ships as a single ASP.NET Core binary — no Node, no PHP, no external build pipeline. Install it on any server you control, point a domain at it, and write.

Philosophy. Inkwell is deliberately small. It ships the things you actually need and almost nothing else. If a feature isn't here, that's usually intentional.

Core concepts

  • Tenants — one Inkwell install can host many blogs. Each tenant has its own domain, Layout, Preset, authors, and database schema.
  • Layouts — structural templates: Magazine, Grid, Minimal, Neutral, Classic, Modern.
  • Presets — ten surface styles (colour palette + type scale), swappable without touching content.
  • Editor — a full WYSIWYG editor: compose visually, draft, schedule, autosave, and publish.

Requirements

RuntimeMinimum version
.NET10.0 or later
DatabaseSQL Server 2019+ or SQL Server LocalDB (development)
OSLinux, Windows Server, macOS
Reverse proxynginx, Caddy, Apache, or IIS (recommended)

Installation

1. Clone the repository

$ git clone https://github.com/marutisoftwaresolutions/inkwell
$ cd inkwell

2. Restore packages

$ dotnet restore

3. Configure (see Configuration)

Edit appsettings.json or use environment variables for secrets.

4. Run database migrations

$ dotnet ef database update

5. Run

$ dotnet run --configuration Release
First-run setup. On the first boot, Inkwell creates the default tenant and admin account. Visit /desk/setup to complete configuration.

Quick start

Prefer a fast path? These three commands get you to a running instance with SQL Server LocalDB and a default tenant:

$ git clone https://github.com/marutisoftwaresolutions/inkwell && cd inkwell
$ dotnet ef database update
$ dotnet run

Open http://localhost:5000 and sign in with the credentials printed to the console on first boot.

Configuration

All settings live in appsettings.json. Override any value with an environment variable using the double-underscore convention: Inkwell__Tenants__0__Host.

Root structure

{
  "Inkwell": {
    "Tenants": [ ... ],
    "Database": { ... },
    "Email": { ... }
  }
}

Multi-tenant setup

{
  "Inkwell": {
    "Tenants": [
      {
        "Host": "essays.example.com",
        "Layout": "Magazine",
        "Preset": "01"
      },
      {
        "Host": "notes.example.com",
        "Layout": "Minimal",
        "Preset": "03"
      }
    ]
  }
}

Database

Inkwell runs on Microsoft SQL Server — SQL Server 2019 or later in production, or SQL Server LocalDB for local development.

{
  "Inkwell": {
    "Database": {
      "Provider": "SqlServer",
      "ConnectionString": "Server=localhost;Database=inkwell;User Id=sa;Password=Your_strong_Pass123;TrustServerCertificate=True"
    }
  }
}
KeyDefaultDescription
ProviderSqlServerMicrosoft SQL Server (only supported provider)
ConnectionStringLocalDBStandard SQL Server ADO.NET connection string
Local development. Use Server=(localdb)\\MSSQLLocalDB;Database=inkwell;Trusted_Connection=True; to run against SQL Server LocalDB with no separate server install.

Email (SMTP)

KeyDescription
Email:SmtpHostHostname of your SMTP server
Email:SmtpPortDefault 587 (STARTTLS)
Email:EnableSsltrue recommended
Email:SenderEmailFrom address
Email:RecipientEmailWhere inquiries are delivered
Email:UsernameSMTP auth username (leave blank if none)
Email:PasswordSMTP auth password — use a secret manager in production
Never commit credentials. Use dotnet user-secrets locally and environment variables or a vault in production.

Layouts & Presets

Inkwell separates structure (Layout) from surface (Preset). Pick one of each per tenant. Swap them without a rebuild or a migration.

Layouts

NameBest for
MagazineMulti-author publications with drop caps, bylines, departments
GridImage-led or high-volume blogs — a card-and-tile post index
MinimalStripped-back single column, no sidebar, no chrome
NeutralThe restrained editorial default — sensible for almost anything
ClassicThe traditional reverse-chronological blog of dated entries
ModernLarge-type contemporary look with generous whitespace

Presets

Inkwell ships ten colour Presets. Each Preset is a single CSS-variable block — palette, type scale, spacing, and dark-mode adaptation — and any Preset pairs with any Layout. Swap one at any time without touching your content.

Custom themes

A Layout is a set of Razor partials in /Views/Layouts/{Name}/. A Preset is a CSS variable override block in /wwwroot/css/presets/{name}.css. Both are hot-reloaded in development. See the GitHub repository for a full theming guide.

Deployment: Linux / systemd

$ dotnet publish -c Release -o /opt/inkwell
$ sudo nano /etc/systemd/system/inkwell.service
[Unit]
Description=Inkwell Blog

[Service]
WorkingDirectory=/opt/inkwell
ExecStart=/opt/inkwell/Inkwell
Restart=always
RestartSec=10
User=www-data
Environment=ASPNETCORE_ENVIRONMENT=Production

[Install]
WantedBy=multi-user.target
$ sudo systemctl enable --now inkwell

Deployment: Docker

A Dockerfile is included in the repository root. Build and run:

$ docker build -t inkwell .
$ docker run -d -p 8080:8080 \
    -e Inkwell__Database__ConnectionString="..." \
    --name inkwell inkwell

A docker-compose.yml bundling SQL Server (mcr.microsoft.com/mssql/server:2022-latest) and Caddy (for automatic TLS) is available in /deploy/compose/.

Deployment: IIS

  1. Install the .NET 10 Hosting Bundle on the server.
  2. Publish: dotnet publish -c Release -o C:\inetpub\inkwell
  3. Create a new IIS site pointing to C:\inetpub\inkwell.
  4. Set the application pool to No Managed Code.
  5. Ensure the app pool identity has read/write access to the publish directory.

Reverse proxy (nginx)

server {
    listen 443 ssl;
    server_name essays.example.com;

    location / {
        proxy_pass         http://localhost:5000;
        proxy_http_version 1.1;
        proxy_set_header   Upgrade $http_upgrade;
        proxy_set_header   Connection keep-alive;
        proxy_set_header   Host $host;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto $scheme;
        proxy_cache_bypass $http_upgrade;
    }
}
Common questions

Frequently asked about setup.

What .NET version does Inkwell require?
Inkwell requires .NET 10. The SDK is needed for building and publishing; the runtime alone is sufficient for hosting. Any server running .NET 10 on Linux, Windows Server, or macOS can host Inkwell without additional dependencies.
Which databases does Inkwell support?
Inkwell uses Microsoft SQL Server 2019 or later for production, with SQL Server LocalDB ideal for development and single-author setups. The database connection is set via the standard Entity Framework Core connection string in appsettings.json. Each tenant in a multi-tenant install uses an isolated database schema.
How do I upgrade Inkwell to a newer version?
Pull the latest source from GitHub, run dotnet ef database update to apply any new migrations, then rebuild with dotnet publish and redeploy the output. The migration step is safe to run while the previous version is still serving traffic. Always read the changelog entry for breaking-change notes before upgrading across a major version boundary.
How do I add a second blog to an existing Inkwell install?
Inkwell is multi-tenant by default — one install serves unlimited publications. In the admin panel, create a new tenant and map a domain or subdomain to it. Each tenant gets its own isolated database schema, layout, preset, and author list. No second deployment is required.
Can I deploy Inkwell with Docker?
Yes. The repository includes a Dockerfile and a docker-compose.yml with Caddy as a reverse proxy and Microsoft SQL Server (mcr.microsoft.com/mssql/server) as the database. Copy .env.example to .env, set your domain and secrets, then run docker compose up -d from the project root. Compose handles TLS via Caddy's automatic HTTPS.
How do I configure email (SMTP) in Inkwell?
Add your SMTP credentials to the Email section of appsettings.json — Host, Port, Username, Password, and FromAddress. Inkwell uses the .NET MailKit library and supports TLS and STARTTLS. For local development, any SMTP relay or a free Mailtrap.io account works without additional setup.