Deploy Your Own IndieWeb Site on Cloudron with Indiekit
What You’ll Build
By the end of this tutorial, you’ll have:
- A personal website at your own domain
- The ability to post from any Micropub client (Quill, Indiepass, iA Writer)
- Automatic syndication to Mastodon and Bluesky
- Webmentions showing likes, replies, and reposts from across the web
- Optional activity widgets for GitHub, YouTube, Funkwhale, or Last.fm
Live Example: rmendes.net
Prerequisites
Before starting, you’ll need:
- A Cloudron server (self-hosted)
- A domain configured in Cloudron
- Basic familiarity with the command line & cloudron cli
- Git/Docker installed on your local machine
Optional (for syndication and integrations):
- Mastodon account and access token
- Bluesky account and app password
- webmention.io account
- API keys for GitHub, YouTube, Funkwhale, or Last.fm
Part 1: Installation
Step 1: Clone the Repository
git clone https://github.com/rmdes/indiekit-cloudron.git
cd indiekit-cloudron
Step 2: Initialize the Submodule
The Eleventy theme is included as a Git submodule:
git submodule update --init --recursive
Step 3: Build the Cloudron Image
cloudron build
This builds a Docker image containing:
- Indiekit (the publishing server)
- Eleventy (the static site generator)
- nginx (for serving static files and proxying)
- All required plugins and dependencies
Note: The first build takes several minutes. Subsequent builds are faster due to caching.
Step 4: Install to Cloudron
cloudron install --app yourdomain.com
Replace yourdomain.com with your actual domain configured in Cloudron.
Step 5: Verify Installation
Visit your domain. You should see a basic site with “Blog coming soon” or similar placeholder content. The admin interface is available at /admin.
Part 2: Basic Configuration
Step 6: Access the Container
cloudron exec --app yourdomain.com
Step 7: Create Your Environment Configuration
cd /app/data/config
cp /app/pkg/env.example env.sh
nano env.sh
Configure the required variables:
# Required - Your site identity
export SITE_URL="https://yourdomain.com"
export SITE_NAME="Your Site Name"
export AUTHOR_NAME="Your Name"
# Optional - Author details
export AUTHOR_BIO="A short bio about yourself"
export AUTHOR_EMAIL="you@example.com"
export AUTHOR_AVATAR="/images/avatar.jpg"
export AUTHOR_LOCATION="City, Country"
# Optional - Social links (for rel="me" verification)
export SOCIAL_GITHUB="https://github.com/yourusername"
export SOCIAL_MASTODON="https://mastodon.social/@yourusername"
export SOCIAL_BLUESKY="https://bsky.app/profile/yourdomain.com"
Step 8: Restart the App
Exit the container (exit) and restart:
cloudron restart --app yourdomain.com
Visit your site - you should now see your configured site name and author information.
Part 3: Setting Up Syndication
Syndication lets you automatically cross-post to social networks when you publish.
Mastodon Syndication
Get a Mastodon Access Token
- Log into your Mastodon instance
- Go to Preferences → Development → New Application
- Name it “Indiekit”
- Select scopes:
read,write:statuses,write:media - Submit and copy the access token
Configure in env.sh
export MASTODON_ACCESS_TOKEN="your-access-token-here"
The Mastodon instance URL and username are configured in indiekit.config.js (see Part 6).
Bluesky Syndication
Create an App Password
- Log into bsky.app
- Go to Settings → App Passwords
- Create a new app password
- Copy the password (you won’t see it again)
Configure in env.sh
export BLUESKY_PASSWORD="your-app-password-here"
Your Bluesky handle is configured in indiekit.config.js.
Bridgy for Backfeed
Bridgy pulls responses (likes, reposts, replies) from social networks back to your site as webmentions.
- Visit brid.gy
- Connect your Mastodon and/or Bluesky accounts
- Bridgy will automatically send webmentions when people interact with your syndicated posts
Part 4: Setting Up Webmentions
Webmentions let other websites notify you when they link to your content.
Step 1: Sign Up for webmention.io
- Visit webmention.io
- Sign in with your domain (uses IndieAuth)
- Go to Settings and copy your API token
Step 2: Configure in env.sh
export WEBMENTION_IO_TOKEN="your-webmention-io-token"
Step 3: Verify Webmention Endpoints
Your site already includes the required <link> tags for webmention discovery. Verify at webmention.rocks.
Part 5: Optional Integrations
These plugins display activity from external services on your site.
GitHub Activity
Shows your commits, stars, PRs, and featured repositories.
Get a GitHub Token
- Go to GitHub → Settings → Developer settings → Personal access tokens → Fine-grained tokens
- Create a token with
public_reporead access - Copy the token
Configure in env.sh
export GITHUB_TOKEN="your-github-token"
YouTube Channel
Displays your latest videos and live streaming status.
Get a YouTube API Key
- Go to Google Cloud Console
- Create a project or select existing
- Enable “YouTube Data API v3”
- Go to Credentials → Create Credentials → API Key
- (Optional) Restrict to YouTube Data API only
Configure in env.sh
export YOUTUBE_API_KEY="your-youtube-api-key"
export YOUTUBE_CHANNELS="@YourChannel,@AnotherChannel"
Funkwhale Listening Activity
Shows your listening history from a Funkwhale instance.
Get a Funkwhale Token
- Log into your Funkwhale instance
- Go to Settings → Applications
- Create an application with read permissions
- Copy the access token
Configure in env.sh
export FUNKWHALE_INSTANCE="https://funkwhale.example.com"
export FUNKWHALE_USERNAME="yourusername"
export FUNKWHALE_TOKEN="your-funkwhale-token"
Last.fm Scrobbles
Shows your listening history from Last.fm.
Get a Last.fm API Key
- Visit last.fm/api/account/create
- Create an API account
- Copy the API key
Configure in env.sh
export LASTFM_API_KEY="your-lastfm-api-key"
export LASTFM_USERNAME="yourusername"
Part 6: Customizing indiekit.config.js
For advanced configuration, you can customize the Indiekit config.
Step 1: Copy the Template
cloudron exec --app yourdomain.com
cp /app/pkg/indiekit.config.js.template /app/data/config/indiekit.config.js
nano /app/data/config/indiekit.config.js
Step 2: Key Configuration Options
export default {
application: {
mongodbUrl: process.env.MONGODB_URL,
url: process.env.CLOUDRON_APP_URL,
name: "Your Site Name",
locale: "en",
timeZone: "Europe/London", // Change to your timezone
},
publication: {
me: "https://yourdomain.com",
categories: ["blog", "notes", "links", "photos"],
},
// Mastodon configuration
"@indiekit/syndicator-mastodon": {
url: "https://mastodon.social", // Your instance
user: "yourusername",
accessToken: process.env.MASTODON_ACCESS_TOKEN,
checked: true, // Enable by default when posting
},
// Bluesky configuration
"@indiekit/syndicator-bluesky": {
handle: "yourdomain.com", // Or your-handle.bsky.social
password: process.env.BLUESKY_PASSWORD,
checked: true,
},
// GitHub plugin
"@rmdes/indiekit-endpoint-github": {
mountPath: "/githubapi",
username: "yourusername",
token: process.env.GITHUB_TOKEN,
featuredRepos: [
"yourusername/cool-project",
"yourusername/another-project",
],
},
// ... other plugins
};
Step 3: Restart After Changes
exit
cloudron restart --app yourdomain.com
Part 7: Publishing Your First Post
Option 1: Using the Built-in Editor
- Visit
https://yourdomain.com/admin - Sign in with IndieAuth (your domain)
- Click “Create” → “Note”
- Write your post
- Check syndication targets (Mastodon, Bluesky)
- Publish
Option 2: Using Quill
- Visit quill.p3k.io
- Sign in with your domain
- Authorize Quill to post to your site
- Compose and publish
Option 3: Using Indigenous (iOS)
- Install Indigenous from the App Store
- Add your site URL
- Authenticate with IndieAuth
- Post from your phone
Part 8: Customizing the Theme
The Eleventy theme can be customized by creating override files.
Theme Structure
eleventy-site/
├── _includes/
│ ├── layouts/ # Page layouts
│ │ ├── base.njk # Base HTML template
│ │ ├── home.njk # Homepage layout
│ │ └── post.njk # Individual post layout
│ └── components/ # Reusable components
├── _data/ # Site data files
├── css/
│ └── tailwind.css # Custom styles
└── content/ # Your posts (symlinked to /app/data/content)
Adding Custom CSS
Edit eleventy-site/css/tailwind.css to add custom styles:
@tailwind base;
@tailwind components;
@tailwind utilities;
/* Your custom styles */
.custom-class {
@apply text-primary-600 dark:text-primary-400;
}
Modifying Templates
Templates use Nunjucks syntax. Key files:
_includes/layouts/home.njk- Homepage layout_includes/layouts/post.njk- Post template with syndication, webmentions_includes/components/- Header, footer, navigation, etc.
After modifying theme files, rebuild and redeploy:
cloudron build --no-cache
cloudron update --app yourdomain.com
Part 9: Maintenance
Viewing Logs
cloudron logs -f --app yourdomain.com
Manual Eleventy Rebuild
If posts aren’t appearing, trigger a manual rebuild:
cloudron exec --app yourdomain.com -- bash -c "cd /app/pkg/eleventy-site && ./node_modules/.bin/eleventy --output=/app/data/site"
Updating the App
When updates are released:
cd indiekit-cloudron
git pull
git submodule update --remote
cloudron build --no-cache
cloudron update --app yourdomain.com
Backup
Cloudron automatically backs up /app/data/ which includes:
- Your content (
/app/data/content/) - Generated site (
/app/data/site/) - Configuration (
/app/data/config/) - Uploaded images (
/app/data/images/)
Troubleshooting
“Blog coming soon” instead of content
The Eleventy build failed. Check logs:
cloudron logs -f --app yourdomain.com
Common causes:
- Template syntax errors
- Missing environment variables
- Permission issues
Posts not syndicating
- Verify tokens in
env.share correct - Check that syndicators are enabled in
indiekit.config.js - Look for errors in logs after posting
Webmentions not appearing
- Verify
WEBMENTION_IO_TOKENis set - Check webmention.io dashboard for received mentions
- Webmentions are fetched at build time - trigger a rebuild
Admin login failing
IndieAuth requires proper <link rel="me"> tags and authorization endpoint. Verify your homepage includes:
<link rel="authorization_endpoint" href="https://yourdomain.com/auth">
<link rel="token_endpoint" href="https://yourdomain.com/auth/token">
Architecture Reference
┌─────────────────────────────────────────────────────┐
│ nginx (port 3000) │
│ Static files + Proxy to Indiekit │
└─────────────────┬───────────────────────────────────┘
│
┌───────────┴───────────┐
│ │
▼ ▼
┌─────────────┐ ┌─────────────┐
│ Eleventy │ │ Indiekit │
│ (watcher) │ │ (port 8080) │
│ │ │ │
│ Builds HTML │ │ Micropub │
│ from content│◄──────│ IndieAuth │
│ │ │ Syndication │
└─────────────┘ └─────────────┘
│ │
▼ ▼
┌─────────────────────────────────────────────────────┐
│ /app/data (persistent) │
│ content/ site/ config/ images/ uploads/ │
└─────────────────────────────────────────────────────┘
Resources
Related Repositories
All my forks/new indiekit repo’s are here
Questions or issues? Open an issue on GitHub or find me on the IndieWeb chat.
AI: Text Editorial · Code AI-assisted · Claude
Editorial assistance — article drafted by human, AI helped with structure and clarity

Comments
Sign in with your website to comment:
Loading comments...
No comments yet. Be the first to share your thoughts!