* Updated landing page

* Added caching policy to landing page Caddy config
* Added radicale
* Added cryptpad
* Added jellyfin
This commit is contained in:
Ellis Rahhal 2024-11-24 11:38:11 -08:00
parent 63545a5c96
commit ddd2e5f9cb
19 changed files with 731 additions and 377 deletions

View file

@ -6,10 +6,10 @@
homefree-inputs.nixos-generators.nixosModules.all-formats
homefree-inputs.nixos-hardware.nixosModules.common-cpu-intel
homefree-inputs.nixos-hardware.nixosModules.common-pc-laptop
homefree-inputs.disko.nixosModules.disko
homefree-inputs.sops-nix.nixosModules.sops
homefree-inputs.authentik-nix.nixosModules.default
homefree-inputs.disko.nixosModules.disko
homefree-inputs.nixvim.nixosModules.nixvim
homefree-inputs.sops-nix.nixosModules.sops
./modules/ddclient-multi.nix
./module.nix
./hosts/homefree/configuration.nix

View file

@ -1,6 +1,7 @@
{ config, lib, ... }:
{
imports = [
../../profiles/acme.nix
../../profiles/common.nix
../../profiles/config-editor.nix
../../profiles/git.nix
@ -13,10 +14,12 @@
../../services/adguardhome.nix
../../services/authentik.nix
../../services/cryptpad.nix
../../services/ddclient.nix
../../services/dnsmasq.nix
../../services/home-assistant
../../services/gitea.nix
../../services/jellyfin.nix
../../services/postgres.nix
../../services/radicale.nix
../../services/unbound.nix

View file

@ -318,6 +318,26 @@
};
};
cryptpad = {
enable = lib.mkOption {
type = lib.types.bool;
default = false;
description = "enable Cryptpad Document service";
};
public = lib.mkOption {
type = lib.types.bool;
default = false;
description = "Open to public on WAN port";
};
adminKeys = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [];
description = "Public keys that have access to admin panel";
};
};
homeassistant = {
enable = lib.mkOption {
type = lib.types.bool;
@ -346,6 +366,20 @@
};
};
jellyfin = {
enable = lib.mkOption {
type = lib.types.bool;
default = false;
description = "enable Jellyfin media server";
};
public = lib.mkOption {
type = lib.types.bool;
default = false;
description = "Open to public on WAN port";
};
};
radicale = {
enable = lib.mkOption {
type = lib.types.bool;

11
profiles/acme.nix Normal file
View file

@ -0,0 +1,11 @@
{ config, ... }:
{
## Required by Cryptpad and potentially other services
security.acme = {
defaults = {
## @TODO: Replace with a real email from config
email = "${config.homefree.system.adminUsername}@${config.homefree.system.domain}";
};
acceptTerms = true;
};
}

View file

@ -45,11 +45,12 @@ in
## @TODO: Remove headers and check if still works
extraConfig = ''
header {
# Add general security headers
Strict-Transport-Security "max-age=31536000; includeSubdomains"
X-XSS-Protection "1; mode=block"
X-Content-Type-Options "nosniff"
X-Frame-Options "SAMEORIGIN"
Referrer-Policy "same-origin"
Referrer-Policy "strict-origin-when-cross-origin"
X-XSS-Protection "1; mode=block"
}
'' + (if entry.public == false then ''
bind 10.0.0.1 192.168.2.1
@ -76,17 +77,67 @@ in
output file ${config.services.caddy.logDir}/access-landing-page.log
'';
extraConfig = ''
header {
Cache-Control: no-cache, no-store, must-revalidate
Strict-Transport-Security "max-age=31536000; includeSubdomains"
X-XSS-Protection "1; mode=block"
X-Content-Type-Options "nosniff"
X-Frame-Options "SAMEORIGIN"
Referrer-Policy "same-origin"
}
bind 10.0.0.1 192.168.2.1 ${config.homefree.system.domain}
root * ${config.homefree.landing-page.path}
file_server
# Enable Gzip compression
encode gzip
# HTML files - No caching to ensure fresh content
@html {
file
path *.html
}
header @html {
# Disable caching for HTML
Cache-Control "no-cache, must-revalidate"
# Add ETag for conditional requests
ETag
# Add Last-Modified header
+Last-Modified
}
# CSS files - Aggressive caching with revalidation
@css {
file
path *.css
}
header @css {
# Cache for 1 year, but allow revalidation
Cache-Control "public, max-age=31536000, stale-while-revalidate=86400"
ETag
+Last-Modified
Vary Accept-Encoding
}
# Assets (CSS, JS, images)
@assets {
file
path *.js *.png *.jpg *.jpeg *.gif *.svg *.woff *.woff2
}
header @assets {
# Cache for 1 hour, but allow revalidation
Cache-Control "public, max-age=3600, must-revalidate"
# Add ETag for conditional requests
ETag
# Add Last-Modified header
+Last-Modified
# Add Vary header to handle different client capabilities
Vary Accept-Encoding
}
# General headers
header {
# Remove Server header for security
-Server
# Add general security headers
Strict-Transport-Security "max-age=31536000; includeSubdomains"
X-Content-Type-Options "nosniff"
X-Frame-Options "SAMEORIGIN"
Referrer-Policy "strict-origin-when-cross-origin"
X-XSS-Protection "1; mode=block"
}
'';
};
}

28
services/cryptpad.nix Normal file
View file

@ -0,0 +1,28 @@
{ config, ... }:
{
services.cryptpad = {
enable = config.homefree.services.cryptpad.enable;
configureNginx = false;
settings = {
httpPort = 3004;
httpAddress = "10.0.0.1";
blockDailyCheck = true;
httpUnsafeOrigin = "https://cryptpad.${config.homefree.system.domain}";
httpSafeOrigin = "https://cryptpad-ui.${config.homefree.system.domain}";
# Add this after you've signed up in your Cryptpad instance and copy your public key:
# adminKeys = [ "[user@cryptpad.example.com/Jil1apEPZ40j5M8nsjO1-deadbeefHkt+QExscMzKhs=]" ];
};
};
homefree.proxied-hosts = if config.homefree.services.cryptpad.enable == true then [
{
label = "cryptpad";
subdomains = [ "cryptpad" "cryptpad-sandbox" "cryptpad-ui" ];
http-domains = [ "homefree.${config.homefree.system.localDomain}" ];
https-domains = [ config.homefree.system.domain ];
port = 3004;
public = config.homefree.services.cryptpad.public;
}
] else [];
}

71
services/jellyfin.nix Normal file
View file

@ -0,0 +1,71 @@
{ config, pkgs, ... }:
{
services.jellyfin = {
enable = config.homefree.services.jellyfin.enable;
openFirewall = true;
user = config.homefree.system.adminUsername;
};
environment.systemPackages = [
pkgs.jellyfin
pkgs.jellyfin-web
pkgs.jellyfin-ffmpeg
];
## Support Intro Skipper plugin
nixpkgs.overlays = with pkgs; [
(
final: prev:
{
jellyfin-web = prev.jellyfin-web.overrideAttrs (finalAttrs: previousAttrs: {
installPhase = ''
runHook preInstall
# this is the important line
sed -i "s#</head>#<script src=\"configurationpage?name=skip-intro-button.js\"></script></head>#" dist/index.html
mkdir -p $out/share
cp -a dist $out/share/jellyfin-web
runHook postInstall
'';
});
}
)
];
homefree.proxied-hosts = if config.homefree.services.jellyfin.enable == true then [
{
label = "jellyfin";
subdomains = [ "jellyfin" ];
http-domains = [ "homefree.${config.homefree.system.localDomain}" ];
https-domains = [ config.homefree.system.domain ];
port = 8096;
public = config.homefree.services.jellyfin.public;
}
] else [];
##--------------------------------------------------------------------------------
## Enable hardware transcoding
## Only works on Intel
## @TODO: Move to hardware config
## @TODO: Add flags for which capabilities are needed by each service
##--------------------------------------------------------------------------------
## enable vaapi on OS-level
nixpkgs.config.packageOverrides = pkgs: {
vaapiIntel = pkgs.vaapiIntel.override { enableHybridCodec = true; };
};
hardware.graphics = {
enable = true;
extraPackages = with pkgs; [
intel-media-driver
intel-vaapi-driver # previously vaapiIntel
vaapiVdpau
intel-compute-runtime # OpenCL filter support (hardware tonemapping and subtitle burn-in)
vpl-gpu-rt # QSV on 11th gen or newer
intel-media-sdk # QSV up to 11th gen
];
};
}

View file

@ -16,7 +16,7 @@
homefree.proxied-hosts = if config.homefree.services.radicale.enable == true then [
{
label = "radicale";
subdomains = [ "radicale" "webdav" "caldav" "carddav" ];
subdomains = [ "radicale" "dav" "webdav" "caldav" "carddav" ];
http-domains = [ "homefree.${config.homefree.system.localDomain}" ];
https-domains = [ config.homefree.system.domain ];
port = 5232;

View file

@ -4,5 +4,5 @@ buildNpmPackage {
name = "site";
src = ./.;
# npmDepsHash = lib.fakeHash;
npmDepsHash = "sha256-+laHFZIwVqx9A8lim6amX5HdfCFkgFiU5QHHScV5lSY=";
npmDepsHash = "sha256-uOLu/MrHS+Et9yUyZO66ANRCzG15hki+7oSTqw4eyT0=";
}

View file

@ -1,12 +1,12 @@
{
"name": "homefree-site",
"version": "0.0.1",
"version": "0.0.2",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "homefree-site",
"version": "0.0.1",
"version": "0.0.2",
"dependencies": {
"@11ty/eleventy": "^3.0.0",
"@11ty/eleventy-plugin-rss": "^2.0.2",

View file

@ -1,6 +1,6 @@
{
"name": "homefree-site",
"version": "0.0.1",
"version": "0.0.2",
"private": true,
"type": "module",
"dependencies": {

83
site/src/comparison.html Normal file
View file

@ -0,0 +1,83 @@
---
title: HomeFree Product Comparison
layout: base.html
---
<div class="container">
<div class="section-header">
<h1>Product Comparison</h1>
</div>
<div class="section">
There are similar systems out there but they are all missing important pieces of the puzzles to make a self-hosted
system simple and turnkey. A goal is to be able to provide a elegant Apple-like design experience in a small box with
built-in battery backup and redundant storage that you plug into your modem instead of a router, and go through a
short installation process and be up and running in minutes. There is currently no other product that does all of
the following out of the box without heavy technical lifting.
<ul style="margin-top: 0.5rem; margin-left: 1.5rem;">
<li>Router/Gateway</li>
<li>Firewall</li>
<li>Wireless Access Point</li>
<li>Ad Blocking</li>
<li>Dynamic DNS</li>
<li>Reverse Proxy with automatic certificate management</li>
<li>Full Application Suite</li>
<li>Single Sign-On</li>
<li>NAS</li>
</ul>
</div>
<div class="section">
<h2>OPNSense/PFSense</h2>
<p>
<a href="https://opnsense.org/" target="_blank">OPNSense</a> and <a href="https://www.pfsense.org/" target="_blank">PFSense</a>
are popular Open Source router products that can replace a typical router/access point provided
by an ISP, with a lot of additional functionality like firewall functionality, ad blocking, intrusion detection,
etc. These products can be used at home, but are rather technical and complicated, requiring a lot of configuration.
They are also not very suitable for serving general applications.
</p>
</div>
<div class="section">
<h2>Ubiquiti Dream Machine Pro</h2>
<p>
The <a href="https://store.ui.com/us/en/products/udm-pro" target="_blank">Ubiquiti Dream Machine Pro</a> is a
similar product to OPNSense, but with a highly polished front-end. It is a corporate product, and as such is
not free, nor is it open source. It also does not work well with other network hardware that is not part of the
Ubiquiti ecosystem. It is also a relatively complex product that requires a level of technical understanding.
</p>
</div>
<div class="section">
<h2>Synology</h2>
<p>
<a href="https://www.synology.com" target="_blank">Synology</a> offers a wide range of products that began with
NAS (Network-Attached Storage) but has extended into offering the ability to run applications in docker containers.
Since they are first and formost network storage devices, they often don't come with much memory and CPU power,
so are not well suited to heavy application usage. Thye also are expensive and not open source, and not purpose
built as routers for WAN facing applications.
</p>
</div>
<div class="section">
<h2>TrueNAS</h2>
<p>
<a href="https://www.truenas.com/" target="_blank">TrueNAS</a> TrueNAS covers a similar NAS space to Synology,
but with an open source offering. Being open source, it can be run on better hardware and can more suitably serve
applications, but is not purpose built as a router, and would require heavy configuration to work as one.
</p>
</div>
<div class="section">
<h2>CasaOS and Umbrel</h2>
<p>
<a href="https://casaos.io/" target="_blank">CasaOS</a> and <a href="https://umbrel.com/" target="_blank">Umbrel</a>
are focused on serving applications as a first class concern, but less capable in routing
and gateway capability, which would need to be configured separately. From a user experience perspective though,
they are closer to what HomeFree is trying to achieve.
</p>
</div>
<div class="section">
<h2>NextCloud and YunoHost</h2>
<p>
<a href="https://nextcloud.com/" target="_blank">NextCloud</a> and <a href="https://yunohost.org/" target="_blank">YunoHost</a>
are heavy multi-purpose web platforms with a built-in suite of applications. They serve a more narrow niche than CasaOS
and Umbrel as they cannot run arbitrary applications, but rather those built specifically for the NextCloud ecosystem.
</p>
</div>
</div>

View file

@ -1,192 +0,0 @@
:root {
--bg-primary: #0f172a;
--bg-secondary: #1e293b;
--text-primary: #e2e8f0;
--text-secondary: #94a3b8;
--accent: #3b82f6;
--max-width: 1200px;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: "SF Pro Display", -apple-system, sans-serif;
background-color: var(--bg-primary);
color: var(--text-primary);
line-height: 1.7;
font-weight: 400; /* More substantial body text */
}
.self-hosted-banner {
background: linear-gradient(90deg, #1e40af, #3b82f6); /* Darker gradient for better contrast */
color: #ffffff; /* Pure white text */
text-align: center;
padding: 0.75rem; /* Slightly taller */
font-size: 0.875rem;
letter-spacing: 0.05em;
text-transform: uppercase;
text-shadow: 0 1px 2px rgba(0,0,0,0.2); /* Subtle shadow for better readability */
}
.self-hosted-banner strong {
font-weight: 600; /* Bolder text for emphasis */
color: #ffffff; /* Ensure strong text is also white */
}
header {
background-color: var(--bg-secondary);
padding: 1rem 0;
position: sticky;
top: 0;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.container {
max-width: var(--max-width);
margin: 0 auto;
padding: 0 2rem;
}
nav {
display: flex;
justify-content: space-between;
align-items: center;
}
.logo {
font-size: 1.75rem;
font-weight: 500; /* More substantial logo */
color: var(--accent);
letter-spacing: -0.04em;
}
nav ul {
display: flex;
gap: 2.5rem;
list-style: none;
}
nav a {
color: var(--text-primary);
text-decoration: none;
transition: color 0.2s;
font-weight: 400; /* More balanced nav items */
font-size: 1rem;
letter-spacing: 0.02em;
}
nav a:hover {
color: var(--accent);
}
.hero {
padding: 6rem 0;
text-align: center;
}
.hero h1 {
font-size: 4rem;
margin-bottom: 1.5rem;
font-weight: 500; /* More substantial heading */
letter-spacing: -0.05em;
line-height: 1.1;
}
.hero p {
font-size: 1.5rem;
color: var(--text-secondary);
max-width: 700px;
margin: 0 auto;
font-weight: 400; /* More balanced hero text */
letter-spacing: -0.02em;
}
.features {
padding: 4rem 0;
background-color: var(--bg-secondary);
}
.features h2 {
font-size: 2.5rem;
font-weight: 500; /* More substantial section heading */
letter-spacing: -0.04em;
}
.features-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 2rem;
margin-top: 3rem;
}
.feature-card {
padding: 2rem;
background-color: var(--bg-primary);
border-radius: 0.5rem;
transition: transform 0.2s;
}
.feature-card:hover {
transform: translateY(-5px);
}
.feature-card h3 {
margin-bottom: 1rem;
color: var(--accent);
font-size: 1.5rem;
font-weight: 500; /* More substantial card headings */
letter-spacing: -0.03em;
}
.feature-card p {
font-size: 1rem;
line-height: 1.7;
color: var(--text-secondary);
font-weight: 400; /* More balanced card text */
}
.cta {
padding: 4rem 0;
text-align: center;
}
.button {
display: inline-block;
padding: 0.875rem 2.5rem;
background-color: var(--accent);
color: white;
text-decoration: none;
border-radius: 0.25rem;
transition: background-color 0.2s;
font-weight: 500; /* More substantial button text */
font-size: 1rem;
letter-spacing: 0.02em;
}
.button:hover {
background-color: #2563eb;
}
footer {
background-color: var(--bg-secondary);
padding: 2rem 0;
text-align: center;
color: var(--text-secondary);
font-size: 0.875rem;
font-weight: 400; /* More balanced footer text */
letter-spacing: 0.02em;
}
@media (max-width: 768px) {
.hero h1 {
font-size: 3rem;
}
nav ul {
gap: 1.5rem;
}
}

View file

@ -1,145 +0,0 @@
:root {
--bg-primary: #0f172a;
--bg-secondary: #1e293b;
--text-primary: #e2e8f0;
--text-secondary: #94a3b8;
--accent: #3b82f6;
--max-width: 1200px;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: system-ui, -apple-system, sans-serif;
background-color: var(--bg-primary);
color: var(--text-primary);
line-height: 1.6;
}
header {
background-color: var(--bg-secondary);
padding: 1.5rem 0;
position: sticky;
top: 0;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.container {
max-width: var(--max-width);
margin: 0 auto;
padding: 0 2rem;
}
nav {
display: flex;
justify-content: space-between;
align-items: center;
}
.logo {
font-size: 1.5rem;
font-weight: bold;
color: var(--accent);
}
nav ul {
display: flex;
gap: 2rem;
list-style: none;
}
nav a {
color: var(--text-primary);
text-decoration: none;
transition: color 0.2s;
}
nav a:hover {
color: var(--accent);
}
.hero {
padding: 6rem 0;
text-align: center;
}
.hero h1 {
font-size: 3.5rem;
margin-bottom: 1.5rem;
}
.hero p {
font-size: 1.25rem;
color: var(--text-secondary);
max-width: 600px;
margin: 0 auto;
}
.features {
padding: 4rem 0;
background-color: var(--bg-secondary);
}
.features-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 2rem;
margin-top: 3rem;
}
.feature-card {
padding: 2rem;
background-color: var(--bg-primary);
border-radius: 0.5rem;
transition: transform 0.2s;
}
.feature-card:hover {
transform: translateY(-5px);
}
.feature-card h3 {
margin-bottom: 1rem;
color: var(--accent);
}
.cta {
padding: 4rem 0;
text-align: center;
}
.button {
display: inline-block;
padding: 1rem 2rem;
background-color: var(--accent);
color: white;
text-decoration: none;
border-radius: 0.25rem;
transition: background-color 0.2s;
}
.button:hover {
background-color: #2563eb;
}
footer {
background-color: var(--bg-secondary);
padding: 2rem 0;
text-align: center;
color: var(--text-secondary);
}
@media (max-width: 768px) {
.hero h1 {
font-size: 2.5rem;
}
nav ul {
gap: 1rem;
}
}

View file

@ -226,7 +226,7 @@ nav a:hover {
width: 100%;
max-width: var(--max-width);
margin: 0 auto;
padding: 4rem 0;
padding: 2rem 0;
display: flex;
flex-direction: column;
align-items: center;
@ -269,7 +269,7 @@ nav a:hover {
align-items: center;
}
.step {
.section {
margin-bottom: 2rem;
max-width: 800px;
width: 100%;
@ -277,11 +277,7 @@ nav a:hover {
margin-right: auto;
}
.step:last-child {
margin-bottom: 0;
}
.step h2 {
.section h2 {
font-size: 1.75rem;
font-weight: 500;
color: var(--accent);
@ -304,15 +300,15 @@ nav a:hover {
font-weight: 500;
}
.step p,
.step .code-block,
.step .note,
.step ul {
.sectionp p,
.sectionp .code-block,
.sectionp .note,
.sectionp ul {
width: 100%;
text-align: left;
}
.step p {
.section p {
margin-top: 1rem;
}
@ -362,6 +358,147 @@ nav a:hover {
color: #666;
}
.section-header {
text-align: center;
padding: 2rem 0 0 0;
}
.section-header h1 {
font-size: 3rem;
font-weight: 500;
letter-spacing: -0.05em;
margin-bottom: 1.5rem;
background: linear-gradient(90deg, var(--accent), #34d399);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
text-shadow: 0 2px 10px rgba(16, 185, 129, 0.1);
}
.section-header p {
color: var(--text-secondary);
font-size: 1.25rem;
max-width: 800px;
margin: 0 auto 2rem;
}
.faq-categories {
display: flex;
justify-content: center;
gap: 1rem;
margin-bottom: 3rem;
flex-wrap: wrap;
}
.category-button {
background-color: var(--bg-secondary);
color: var(--text-primary);
border: none;
padding: 0.5rem 1.5rem;
border-radius: 2rem;
cursor: pointer;
transition: all 0.2s ease;
font-size: 0.9rem;
}
.category-button:hover,
.category-button.active {
background-color: var(--accent);
color: white;
}
.faq-section {
max-width: 800px;
margin: 0 auto;
padding: 2rem 0;
}
.faq-item {
margin-bottom: 2rem;
background-color: var(--bg-secondary);
border-radius: 0.5rem;
overflow: hidden;
}
.faq-question {
padding: 1.5rem;
cursor: pointer;
display: flex;
justify-content: space-between;
align-items: center;
font-weight: 500;
color: var(--accent);
transition: background-color 0.2s ease;
}
.faq-question:hover {
background-color: rgba(16, 185, 129, 0.1);
}
.faq-question::after {
content: '+';
font-size: 1.5rem;
color: var(--accent);
}
.faq-answer {
padding: 1.5rem 1.5rem 1.5rem;
color: var(--text-secondary);
}
.faq-answer p {
margin-top: 1rem;
}
.comparison-table {
width: 100%;
max-width: 1000px;
margin: 2rem auto;
border-collapse: collapse;
font-family: system-ui, -apple-system, sans-serif;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
border-radius: 8px;
overflow: hidden;
}
.comparison-table th {
background-color: #f8fafc;
padding: 1rem;
text-align: left;
font-weight: 600;
color: #1e293b;
border-bottom: 2px solid #e2e8f0;
}
.comparison-table td {
padding: 1rem;
border-bottom: 1px solid #e2e8f0;
color: #475569;
}
.comparison-table tr:last-child td {
border-bottom: none;
}
.comparison-table tr:hover td {
background-color: #f1f5f9;
}
.feature-available {
color: #16a34a;
font-weight: 500;
}
.feature-unavailable {
color: #dc2626;
}
.price {
font-size: 1.25rem;
font-weight: 600;
color: #0f172a;
}
.note {
background-color: var(--bg-secondary);
padding: 1rem 1.5rem;
@ -398,8 +535,17 @@ footer {
font-size: 2.5rem;
}
.step h2 {
.section h2 {
font-size: 1.5rem;
}
.section-header h1 {
font-size: 2.5rem;
}
.faq-question,
.faq-answer {
padding: 1rem;
}
}

250
site/src/faq.html Normal file
View file

@ -0,0 +1,250 @@
---
title: HomeFree FAQs
layout: base.html
---
<div class="container">
<div class="section-header">
<h1>Frequently Asked Questions</h1>
<!--
<p>Find answers to common questions about ProjectName, from basic setup to advanced features.</p>
<div class="faq-categories">
<button class="category-button active">All</button>
<button class="category-button">Reliability</button>
<button class="category-button">Security</button>
<button class="category-button">Deployment</button>
<button class="category-button">Troubleshooting</button>
</div>
-->
</div>
<div class="faq-section">
<div class="faq-item">
<div class="faq-question">
What exactly is HomeFree?
</div>
<div class="faq-answer">
<p>
HomeFree is a project with a singular goal: to allow you to control your own data by drastically reducing your
dependence on big centralized corporate services. The way this is accomplished to to own your own device and host
your own services. This has been possible for a long time but required a lot of experience and months or years of
effort to get anywhere close to making this work in a reliable and usable way.
</p>
<p>
In the process of building a self-hosted setup at home, the realiztion dawned that all the pieces are now
available and commoditized, but there is no easy way to stitch them together and no easy way to configure them.
HomeFree aims to solve this by being very specific about choosing the right configuration and curating a
set of applications to cut through the endless choice and inconsistency of currently available systems, and
adding a single UI with a standard design language and single login to access them all.
</div>
</div>
<div class="faq-item">
<div class="faq-question">
How does it differ from other available solutions?
</div>
<div class="faq-answer">
<p>
There are similar systems out there but they are all missing important pieces of the puzzles to make a self-hosted
system simple and turnkey. A goal is to be able to provide a elegant Apple-like design experience in a small box with
built-in battery backup and redundant storage that you plug directly into your modem and replaces your
router, NAS, home server, and WiFi access point, all through a short installation process to be up and running in minutes.
</p>
<p>
For a detailed comparison with other products, check out the <a href="/comparison">product comparison page</a>.
</p>
</div>
</div>
<div class="faq-item">
<div class="faq-question">
What types of things can I do with HomeFree?
</div>
<div class="faq-answer">
Almost everything that is provided by Google and other large tech companies could be a target for inclusion
in HomeFree. Services that are already included or are in work:
<ul style="margin-top: 0.5rem; margin-left: 1.5rem;">
<li>Photo hosting</li>
<li>Calendar</li>
<li>Contacts</li>
<li>Office Suite</li>
<li>File Storage</li>
<li>Video and Audio Serving</li>
<li>Home Automation</li>
<li>Video surveilance</li>
<li>Website/Blog</li>
<li>Ad Blocking</li>
<li>Password Managemenet</li>
<li>Browser Bookmark Sync</li>
</ul>
</div>
</div>
<div class="faq-item">
<div class="faq-question">
Can I access my server away from home?
</div>
<div class="faq-answer">
Yes! That's one of the core goals of HomeFree - to provide public facing services and access so that
you don't have to rely on large centralized services. You can configure various services to be private
to your home or open to the internet. For services that are private, you can access them remotely by
connecting to HomeFree through a built-in VPN.
</div>
</div>
<div class="faq-item">
<div class="faq-question">
What are more cutting edge ideas that could be implemented?
</div>
<div class="faq-answer">
Anything that could run on a computer or be run as a service could be hosted by HomeFree. The goal is to make
adding modules standard and plug-and-play. AI, privacy, and decentralization are themes that could be explored.
<ul style="margin-top: 0.5rem; margin-left: 1.5rem;">
<li>External GPU plugin for AI services. Could cluster GPUs with friends, family, or even strangers</li>
<li>Decentralized social media nodes such as Bluesky and Mastadon</li>
<li>Decentralized CDNs for high traffic sites and services</li>
<li>Shared back-up services between friends and family</li>
<li>Cryptocurrency (though nothing about HomeFree is currently related to or dependency on a blockchain)</li>
<li>Pluggable DNA sequencing module for those who don't want to use a public DNA sequencing service</li>
</ul>
</div>
</div>
<div class="faq-item">
<div class="faq-question">
Is HomeFree FREE?
</div>
<div class="faq-answer">
Yes, it is free in both major senses of the word - it is open source, so you can install and modify it
as you please. It is also free to use, without payment.
</div>
</div>
<div class="faq-item">
<div class="faq-question">
A stated goal of HomeFree is to be easy to set up. How can this be with the complexities around domain registration,
dynamically allocated IPs, and the complexities of various ISP deployments?
</div>
<div class="faq-answer">
Making these easy are core goals of the project, and the vision is to make them as automatic as possible. The easiest route
would be a web-gui or phone app based configuration that does the following:
<ul style="margin-top: 0.5rem; margin-left: 1.5rem;">
<li>Detect the ISP and automatically configure appropriately</li>
<li>Provide simple insructions on any changes required to the modem configuration, if necessary</li>
<li>Longer term, look at spearheading a movement for zero-config ISP/modem setup for self hosting</li>
<li>Provide a dynamic DNS service with subdomains at homefree.host for zero-effort setup</li>
<li>If a personal domain is desired, provide a simple step-by-tep UI-based config</li>
<li>For personal domains, detect the registrar, and offer custom instructions for setting up dynamic dns</li>
<li>Longer term, look at protocols/APIs for automatically configuring registrars</li>
</ul>
</div>
</div>
<div class="faq-item">
<div class="faq-question">
What about email? Isn't that very hard to self-host?
</div>
<div class="faq-answer">
It's well know among the self-hosting community that email can be fragile and difficult to self-host for various reasons. The
great thing about HomeFree is that it's not all or nothing. You can progressively decide which services you want to host and
which you want to continue to use elsewhere. But there are still plans to offer the ability to host an email server if you
so wish. For an example of a simple US for setting up a custom domain for secure and reliable email, look at Proton Mail's
domain configuration UI.
</div>
</div>
<div class="faq-item">
<div class="faq-question">
What is preventing me from losing all my data if the hardware fails or my house burns down?
</div>
<div class="faq-answer">
The system is designed to store all data in a way that is easy to bundle and back-up to another machine
in your location and off-site as well.
</div>
</div>
<div class="faq-item">
<div class="faq-question">
What if I am in the process of moving or don't want to host a server at my location anymore?
</div>
<div class="faq-answer">
The backup data bundle is in a standard format and can easily be moved to another HomeFree server or
an online HomeFree-compatible service if you do not want to continue hosting yourself.
</div>
</div>
<div class="faq-item">
<div class="faq-question">
How do I ensure that access to my services is reliable when I am using it away from home?
</div>
<div class="faq-answer">
This problem is still under consideration. One potential solution is to share load across multiple HomeFree
servers, either through friends and family, or a more open anonymous distributed CDN of some sort. Also,
paid-for services could be offered that provide a back-up in case your server goes down or is otherwise
out of service.
</div>
</div>
<div class="faq-item">
<div class="faq-question">
How can I contribute to the project?
</div>
<div class="faq-answer">
We welcome contributions of all kinds! You can:
<ul style="margin-top: 0.5rem; margin-left: 1.5rem;">
<li>Submit bug reports and feature requests on our <a href="https://git.homefree.host/homefree">git instance</a></li>
<li>Improve documentation</li>
<li>Submit pull requests</li>
<li>Help others in our community forums</li>
</ul>
Check our <a href="#contribution-guide">contribution guidelines [TBD]</a> to get started.
</div>
</div>
<div class="faq-item">
<div class="faq-question">
What's the license and usage policy?
</div>
<div class="faq-answer">
HomeFree is currently built and copyrighted by Ellis Rahhal. I am currently in the process of evaluating which open source license
to release the project under. Most likely it will be a BSD-based license with limited restrictions to encourage wide adoption.
</div>
</div>
</div>
</div>
<script>
// Simple toggle for FAQ items
document.querySelectorAll('.faq-question').forEach(question => {
question.addEventListener('click', () => {
const answer = question.nextElementSibling;
const isOpen = answer.style.display === 'block';
// Close all answers
document.querySelectorAll('.faq-answer').forEach(a => {
a.style.display = 'none';
});
document.querySelectorAll('.faq-question').forEach(q => {
q.style.removeProperty('background-color');
});
// Toggle clicked answer
if (!isOpen) {
answer.style.display = 'block';
question.style.backgroundColor = 'rgba(16, 185, 129, 0.1)';
}
// Update plus/minus
document.querySelectorAll('.faq-question').forEach(q => {
q.style.setProperty('--content', '"+"');
});
if (!isOpen) {
question.style.setProperty('--content', '"-"');
}
});
});
// Hide all answers initially except the first one
document.querySelectorAll('.faq-answer').forEach((answer, index) => {
answer.style.display = index === 0 ? 'block' : 'none';
});
</script>

View file

@ -9,6 +9,7 @@
<ul>
<li><a href="/#features">Features</a></li>
<li><a href="/quick-start">Docs</a></li>
<li><a href="/faq">FAQ</a></li>
<li><a href="https://git.homefree.host/homefree">Git</a></li>
</ul>
</nav>

View file

@ -1,6 +1,8 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="cache-control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="Pragma" content="no-cache">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta charset="utf-8" />
@ -12,11 +14,22 @@
<noscript><link rel="stylesheet" href="/css/noscript.css" /></noscript>
<title>{{ title }}</title>
</head>
<body>
<body style="visibility: hidden;">
{% include "elements/header.html" %}
<main>
{{ content | safe }}
</main>
{% include "elements/footer.html" %}
<script>
const domReady = (cb) => {
document.readyState === 'interactive' || document.readyState === 'complete'
? cb()
: document.addEventListener('DOMContentLoaded', cb);
};
domReady(() => {
document.body.style.visibility = 'visible';
});
</script>
</body>
</html>

View file

@ -9,7 +9,7 @@ layout: base.html
for users and developers comfortable installing and configuring software on Linux.
</p>
<div class="step">
<div class="section">
<h2><span class="step-number">1</span>Acquire Hardware</h2>
<p>HomeFree has been tested on AMD and Intel-based x86 hardware. The minimum requirements are still in flux,
but you'll want a device that has at least 8Gb of memory and a decent CPU, since it will be running many
@ -19,14 +19,14 @@ layout: base.html
but it surely will run on less expensive hardware.</b>
</div>
<div class="step">
<div class="section">
<h2><span class="step-number">2</span>Get a Nix environment set up on your host machine.</h2>
<p>HomeFree must be deployed from another machine with Nix installed. If you are on NixOS, you should be good to go.
If you are on a different distribution of Linux, follow the <a href="https://nixos.org/download/" target="_blank">instructions</a> on how
to install and use Nix.</p>
</div>
<div class="step">
<div class="section">
<h2><span class="step-number">3</span>Get the code</h2>
<p>Download the <a href="https://git.homefree.host/homefree/sample-config" target="_blank">sample host config</a> to your workstation.</p>
<div class="code-block">
@ -34,18 +34,18 @@ layout: base.html
</div>
</div>
<div class="step">
<div class="section">
<h2><span class="step-number">4</span>Prepare the configuration</h2>
<p>Update configuration.nix with your preferred settings. More details TBD.</p>
</div>
<div class="step">
<div class="section">
<h2><span class="step-number">5</span>Get the IP address of the target machine</h2>
<p>Create a bootable USB flash drive of the minimal NixOS ISO image. Simple instructions can be found <a href="https://nixos.wiki/wiki/NixOS_Installation_Guide/Unetbootin" target="_blank">here</a>.</p>
<p>Boot the target machine with the USB flash drive</p>
</div>
<div class="step">
<div class="section">
<h2><span class="step-number">6</span>Hardware Preparation</h2>
<p>Disable secure boot in the BIOS of the target machine.</p>
<p>Plug the machine into an ethernet cable.</p>
@ -54,7 +54,7 @@ layout: base.html
</div>
</div>
<div class="step">
<div class="section">
<h2><span class="step-number">7</span>Create NixOS bootable flash drive and boot up machine</h2>
<p>After the machine is has booted the minimal NixOS image and you are logged in, get the IP address with the following:</p>
<div class="code-block">
@ -64,7 +64,7 @@ layout: base.html
</div>
</div>
<div class="step">
<div class="section">
<h2><span class="step-number">8</span>Install HomeFree</h2>
<p>Run the installation script. Again, make sure the target computer is connected to an ethernet cable.</p>
<p>Enter the IP of the target machine as directed.</p>
@ -75,7 +75,7 @@ layout: base.html
</div>
</div>
<div class="step">
<div class="section">
<h2><span class="step-number">9</span>Next Steps</h2>
<p>Now that you have a running instance, you should be able to log in with:</p>
<div class="code-block">