* Updated landing page
* Added caching policy to landing page Caddy config * Added radicale * Added cryptpad * Added jellyfin
This commit is contained in:
parent
63545a5c96
commit
ddd2e5f9cb
19 changed files with 731 additions and 377 deletions
|
@ -6,10 +6,10 @@
|
||||||
homefree-inputs.nixos-generators.nixosModules.all-formats
|
homefree-inputs.nixos-generators.nixosModules.all-formats
|
||||||
homefree-inputs.nixos-hardware.nixosModules.common-cpu-intel
|
homefree-inputs.nixos-hardware.nixosModules.common-cpu-intel
|
||||||
homefree-inputs.nixos-hardware.nixosModules.common-pc-laptop
|
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.authentik-nix.nixosModules.default
|
||||||
|
homefree-inputs.disko.nixosModules.disko
|
||||||
homefree-inputs.nixvim.nixosModules.nixvim
|
homefree-inputs.nixvim.nixosModules.nixvim
|
||||||
|
homefree-inputs.sops-nix.nixosModules.sops
|
||||||
./modules/ddclient-multi.nix
|
./modules/ddclient-multi.nix
|
||||||
./module.nix
|
./module.nix
|
||||||
./hosts/homefree/configuration.nix
|
./hosts/homefree/configuration.nix
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{ config, lib, ... }:
|
{ config, lib, ... }:
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
|
../../profiles/acme.nix
|
||||||
../../profiles/common.nix
|
../../profiles/common.nix
|
||||||
../../profiles/config-editor.nix
|
../../profiles/config-editor.nix
|
||||||
../../profiles/git.nix
|
../../profiles/git.nix
|
||||||
|
@ -13,10 +14,12 @@
|
||||||
|
|
||||||
../../services/adguardhome.nix
|
../../services/adguardhome.nix
|
||||||
../../services/authentik.nix
|
../../services/authentik.nix
|
||||||
|
../../services/cryptpad.nix
|
||||||
../../services/ddclient.nix
|
../../services/ddclient.nix
|
||||||
../../services/dnsmasq.nix
|
../../services/dnsmasq.nix
|
||||||
../../services/home-assistant
|
../../services/home-assistant
|
||||||
../../services/gitea.nix
|
../../services/gitea.nix
|
||||||
|
../../services/jellyfin.nix
|
||||||
../../services/postgres.nix
|
../../services/postgres.nix
|
||||||
../../services/radicale.nix
|
../../services/radicale.nix
|
||||||
../../services/unbound.nix
|
../../services/unbound.nix
|
||||||
|
|
34
module.nix
34
module.nix
|
@ -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 = {
|
homeassistant = {
|
||||||
enable = lib.mkOption {
|
enable = lib.mkOption {
|
||||||
type = lib.types.bool;
|
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 = {
|
radicale = {
|
||||||
enable = lib.mkOption {
|
enable = lib.mkOption {
|
||||||
type = lib.types.bool;
|
type = lib.types.bool;
|
||||||
|
|
11
profiles/acme.nix
Normal file
11
profiles/acme.nix
Normal 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;
|
||||||
|
};
|
||||||
|
}
|
|
@ -45,11 +45,12 @@ in
|
||||||
## @TODO: Remove headers and check if still works
|
## @TODO: Remove headers and check if still works
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
header {
|
header {
|
||||||
|
# Add general security headers
|
||||||
Strict-Transport-Security "max-age=31536000; includeSubdomains"
|
Strict-Transport-Security "max-age=31536000; includeSubdomains"
|
||||||
X-XSS-Protection "1; mode=block"
|
|
||||||
X-Content-Type-Options "nosniff"
|
X-Content-Type-Options "nosniff"
|
||||||
X-Frame-Options "SAMEORIGIN"
|
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 ''
|
'' + (if entry.public == false then ''
|
||||||
bind 10.0.0.1 192.168.2.1
|
bind 10.0.0.1 192.168.2.1
|
||||||
|
@ -76,17 +77,67 @@ in
|
||||||
output file ${config.services.caddy.logDir}/access-landing-page.log
|
output file ${config.services.caddy.logDir}/access-landing-page.log
|
||||||
'';
|
'';
|
||||||
extraConfig = ''
|
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}
|
bind 10.0.0.1 192.168.2.1 ${config.homefree.system.domain}
|
||||||
root * ${config.homefree.landing-page.path}
|
root * ${config.homefree.landing-page.path}
|
||||||
file_server
|
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
28
services/cryptpad.nix
Normal 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
71
services/jellyfin.nix
Normal 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
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
|
@ -16,7 +16,7 @@
|
||||||
homefree.proxied-hosts = if config.homefree.services.radicale.enable == true then [
|
homefree.proxied-hosts = if config.homefree.services.radicale.enable == true then [
|
||||||
{
|
{
|
||||||
label = "radicale";
|
label = "radicale";
|
||||||
subdomains = [ "radicale" "webdav" "caldav" "carddav" ];
|
subdomains = [ "radicale" "dav" "webdav" "caldav" "carddav" ];
|
||||||
http-domains = [ "homefree.${config.homefree.system.localDomain}" ];
|
http-domains = [ "homefree.${config.homefree.system.localDomain}" ];
|
||||||
https-domains = [ config.homefree.system.domain ];
|
https-domains = [ config.homefree.system.domain ];
|
||||||
port = 5232;
|
port = 5232;
|
||||||
|
|
|
@ -4,5 +4,5 @@ buildNpmPackage {
|
||||||
name = "site";
|
name = "site";
|
||||||
src = ./.;
|
src = ./.;
|
||||||
# npmDepsHash = lib.fakeHash;
|
# npmDepsHash = lib.fakeHash;
|
||||||
npmDepsHash = "sha256-+laHFZIwVqx9A8lim6amX5HdfCFkgFiU5QHHScV5lSY=";
|
npmDepsHash = "sha256-uOLu/MrHS+Et9yUyZO66ANRCzG15hki+7oSTqw4eyT0=";
|
||||||
}
|
}
|
||||||
|
|
4
site/package-lock.json
generated
4
site/package-lock.json
generated
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "homefree-site",
|
"name": "homefree-site",
|
||||||
"version": "0.0.1",
|
"version": "0.0.2",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "homefree-site",
|
"name": "homefree-site",
|
||||||
"version": "0.0.1",
|
"version": "0.0.2",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@11ty/eleventy": "^3.0.0",
|
"@11ty/eleventy": "^3.0.0",
|
||||||
"@11ty/eleventy-plugin-rss": "^2.0.2",
|
"@11ty/eleventy-plugin-rss": "^2.0.2",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "homefree-site",
|
"name": "homefree-site",
|
||||||
"version": "0.0.1",
|
"version": "0.0.2",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
83
site/src/comparison.html
Normal file
83
site/src/comparison.html
Normal 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>
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -226,7 +226,7 @@ nav a:hover {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: var(--max-width);
|
max-width: var(--max-width);
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding: 4rem 0;
|
padding: 2rem 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
@ -269,7 +269,7 @@ nav a:hover {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.step {
|
.section {
|
||||||
margin-bottom: 2rem;
|
margin-bottom: 2rem;
|
||||||
max-width: 800px;
|
max-width: 800px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -277,11 +277,7 @@ nav a:hover {
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.step:last-child {
|
.section h2 {
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.step h2 {
|
|
||||||
font-size: 1.75rem;
|
font-size: 1.75rem;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: var(--accent);
|
color: var(--accent);
|
||||||
|
@ -304,15 +300,15 @@ nav a:hover {
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.step p,
|
.sectionp p,
|
||||||
.step .code-block,
|
.sectionp .code-block,
|
||||||
.step .note,
|
.sectionp .note,
|
||||||
.step ul {
|
.sectionp ul {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.step p {
|
.section p {
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,6 +358,147 @@ nav a:hover {
|
||||||
color: #666;
|
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 {
|
.note {
|
||||||
background-color: var(--bg-secondary);
|
background-color: var(--bg-secondary);
|
||||||
padding: 1rem 1.5rem;
|
padding: 1rem 1.5rem;
|
||||||
|
@ -398,8 +535,17 @@ footer {
|
||||||
font-size: 2.5rem;
|
font-size: 2.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.step h2 {
|
.section h2 {
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.section-header h1 {
|
||||||
|
font-size: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.faq-question,
|
||||||
|
.faq-answer {
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
250
site/src/faq.html
Normal file
250
site/src/faq.html
Normal 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>
|
|
@ -9,6 +9,7 @@
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="/#features">Features</a></li>
|
<li><a href="/#features">Features</a></li>
|
||||||
<li><a href="/quick-start">Docs</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>
|
<li><a href="https://git.homefree.host/homefree">Git</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<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 charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
|
@ -12,11 +14,22 @@
|
||||||
<noscript><link rel="stylesheet" href="/css/noscript.css" /></noscript>
|
<noscript><link rel="stylesheet" href="/css/noscript.css" /></noscript>
|
||||||
<title>{{ title }}</title>
|
<title>{{ title }}</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body style="visibility: hidden;">
|
||||||
{% include "elements/header.html" %}
|
{% include "elements/header.html" %}
|
||||||
<main>
|
<main>
|
||||||
{{ content | safe }}
|
{{ content | safe }}
|
||||||
</main>
|
</main>
|
||||||
{% include "elements/footer.html" %}
|
{% 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>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -9,7 +9,7 @@ layout: base.html
|
||||||
for users and developers comfortable installing and configuring software on Linux.
|
for users and developers comfortable installing and configuring software on Linux.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="step">
|
<div class="section">
|
||||||
<h2><span class="step-number">1</span>Acquire Hardware</h2>
|
<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,
|
<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
|
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>
|
but it surely will run on less expensive hardware.</b>
|
||||||
</div>
|
</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>
|
<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.
|
<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
|
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>
|
to install and use Nix.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="step">
|
<div class="section">
|
||||||
<h2><span class="step-number">3</span>Get the code</h2>
|
<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>
|
<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">
|
<div class="code-block">
|
||||||
|
@ -34,18 +34,18 @@ layout: base.html
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="step">
|
<div class="section">
|
||||||
<h2><span class="step-number">4</span>Prepare the configuration</h2>
|
<h2><span class="step-number">4</span>Prepare the configuration</h2>
|
||||||
<p>Update configuration.nix with your preferred settings. More details TBD.</p>
|
<p>Update configuration.nix with your preferred settings. More details TBD.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="step">
|
<div class="section">
|
||||||
<h2><span class="step-number">5</span>Get the IP address of the target machine</h2>
|
<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>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>
|
<p>Boot the target machine with the USB flash drive</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="step">
|
<div class="section">
|
||||||
<h2><span class="step-number">6</span>Hardware Preparation</h2>
|
<h2><span class="step-number">6</span>Hardware Preparation</h2>
|
||||||
<p>Disable secure boot in the BIOS of the target machine.</p>
|
<p>Disable secure boot in the BIOS of the target machine.</p>
|
||||||
<p>Plug the machine into an ethernet cable.</p>
|
<p>Plug the machine into an ethernet cable.</p>
|
||||||
|
@ -54,7 +54,7 @@ layout: base.html
|
||||||
</div>
|
</div>
|
||||||
</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>
|
<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>
|
<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">
|
<div class="code-block">
|
||||||
|
@ -64,7 +64,7 @@ layout: base.html
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="step">
|
<div class="section">
|
||||||
<h2><span class="step-number">8</span>Install HomeFree</h2>
|
<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>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>
|
<p>Enter the IP of the target machine as directed.</p>
|
||||||
|
@ -75,7 +75,7 @@ layout: base.html
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="step">
|
<div class="section">
|
||||||
<h2><span class="step-number">9</span>Next Steps</h2>
|
<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>
|
<p>Now that you have a running instance, you should be able to log in with:</p>
|
||||||
<div class="code-block">
|
<div class="code-block">
|
||||||
|
|
Loading…
Add table
Reference in a new issue