Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[VNEXT] feat: Opt-In Anlytics #277

Draft
wants to merge 14 commits into
base: vnext
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ tasks:
desc: Install development dependencies
cmds:
- go install github.com/swaggo/swag/cmd/swag@latest
- go install gotest.tools/gotestsum@latest
- go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
- cd backend && go mod tidy
- cd frontend && pnpm install --shamefully-hoist

Expand Down
48 changes: 48 additions & 0 deletions backend/app/api/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ package main
import (
"bytes"
"context"
"encoding/json"
"fmt"
"github.com/shirou/gopsutil/v4/host"
"net/http"
"os"
"path/filepath"
Expand Down Expand Up @@ -72,6 +74,52 @@ func run(cfg *config.Config) error {
app := new(cfg)
app.setupLogger()

if cfg.Options.AllowAnalytics {
type analyticsData struct {
Domain string `json:"domain"`
Name string `json:"name"`
URL string `json:"url"`
Props map[string]interface{} `json:"props"`
}
hostData, _ := host.Info()
analytics := analyticsData{
Domain: "homebox.software",
URL: "https://homebox.software",
Name: "stats",
Props: map[string]interface{}{
"version": version + "/" + build(),
"os": hostData.OS,
"platform": hostData.Platform,
"platform_family": hostData.PlatformFamily,
"platform_version": hostData.PlatformVersion,
"kernel_arch": hostData.KernelArch,
tankerkiller125 marked this conversation as resolved.
Show resolved Hide resolved
"virt_type": hostData.VirtualizationSystem,
},
}
jsonBody, err := json.Marshal(analytics)
if err != nil {
log.Error().Err(err).Msg("failed to marshal analytics data")
}
bodyReader := bytes.NewReader(jsonBody)
req, err := http.NewRequest("POST", "https://a.sysadmins.zone/api/event", bodyReader)
if err != nil {
log.Error().Err(err).Msg("failed to create analytics request")
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("User-Agent", "Homebox/"+version+"/"+build()+" (https://homebox.software)")
client := &http.Client{
Timeout: 10 * time.Second,
}
res, err := client.Do(req)
if err != nil {
log.Error().Err(err).Msg("failed to send analytics request")
}
err = res.Body.Close()
if err != nil {
log.Error().Err(err).Msg("failed to send analytics request")
}
}

// =========================================================================
// Initialize Database & Repos

Expand Down
8 changes: 8 additions & 0 deletions backend/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ require (
github.com/olahol/melody v1.2.1
github.com/pkg/errors v0.9.1
github.com/rs/zerolog v1.33.0
github.com/shirou/gopsutil/v4 v4.24.9
github.com/stretchr/testify v1.9.0
github.com/swaggo/http-swagger/v2 v2.0.2
github.com/swaggo/swag v1.16.3
Expand All @@ -32,9 +33,11 @@ require (
github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/ebitengine/purego v0.8.0 // indirect
github.com/fatih/color v1.16.0 // indirect
github.com/fogleman/gg v1.3.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-openapi/inflect v0.19.0 // indirect
github.com/go-openapi/jsonpointer v0.20.0 // indirect
github.com/go-openapi/jsonreference v0.20.2 // indirect
Expand All @@ -49,16 +52,21 @@ require (
github.com/hashicorp/hcl/v2 v2.19.1 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
github.com/ncruces/go-strftime v0.1.9 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/rogpeppe/go-internal v1.11.0 // indirect
github.com/swaggo/files/v2 v2.0.0 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
github.com/yeqown/reedsolomon v1.0.0 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
github.com/zclconf/go-cty v1.14.1 // indirect
golang.org/x/image v0.18.0 // indirect
golang.org/x/mod v0.20.0 // indirect
Expand Down
64 changes: 32 additions & 32 deletions backend/go.sum

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions backend/internal/data/repo/repo_items.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,12 @@ type (

// Purchase
PurchaseTime types.Date `json:"purchaseTime"`
PurchaseFrom string `json:"purchaseFrom" validate:"max=255"`
PurchaseFrom string `json:"purchaseFrom" validate:"max=255"`
PurchasePrice float64 `json:"purchasePrice" extensions:"x-nullable,x-omitempty"`

// Sold
SoldTime types.Date `json:"soldTime"`
SoldTo string `json:"soldTo" validate:"max=255"`
SoldTo string `json:"soldTo" validate:"max=255"`
SoldPrice float64 `json:"soldPrice" extensions:"x-nullable,x-omitempty"`
SoldNotes string `json:"soldNotes"`

Expand Down
1 change: 1 addition & 0 deletions backend/internal/sys/config/conf.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ type Options struct {
AllowRegistration bool `yaml:"disable_registration" conf:"default:true"`
AutoIncrementAssetID bool `yaml:"auto_increment_asset_id" conf:"default:true"`
CurrencyConfig string `yaml:"currencies"`
AllowAnalytics bool `yaml:"allow_analytics" conf:"default:false"`
}

type DebugConf struct {
Expand Down
7 changes: 7 additions & 0 deletions docs/.vitepress/menus/en.mts
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,12 @@ export default [
{text: 'Get Started', link: '/en/contribute/get-started'},
{text: 'Bounty Program', link: '/en/contribute/bounty'}
]
},
{
text: 'Analytics',
items: [
{text: 'Current Analytics', link: '/en/analytics'},
{text: 'Privacy Policy', link: '/en/analytics/privacy'}
]
}
]
10 changes: 10 additions & 0 deletions docs/en/analytics/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
## What is This?
We collect non-identifying information from users of Homebox that have opted in to analytics collection. By default users do not send us anything, however once opted in that data gets sent to our own Plausibe instance and the data below is live from that instance.

We make this data public so that everyone knows exactly what's being collected, and so that they can see the data we see as it helps us make some decisions.

## Current Analytics Collected

<iframe plausible-embed src="https://a.sysadmins.zone/share/homebox.software?auth=O2nQ-b8I0oo80RKJXx2Q7&embed=true&theme=system&goal=stats" scrolling="no" frameborder="0" loading="lazy" style="width: 1px; min-width: 100%; height: 100%; min-height: 1600px"></iframe>
<div style="font-size: 14px; padding-bottom: 14px;">Stats powered by <a target="_blank" style="color: #4F46E5; text-decoration: underline;" href="https://plausible.io">Plausible Analytics</a> hosted on our own instance in the UK</div>
<script async src="https://a.sysadmins.zone/js/embed.host.js"></script>
60 changes: 60 additions & 0 deletions docs/en/analytics/privacy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Homebox Privacy Policy

## Introduction

**Homebox** (and by extension; Sysadmins Media) respects the privacy of its users and is committed to protecting the data shared through our application. This privacy policy outlines the types of data collected from users who opt in to analytics, the purposes for which we collect and use this data, how it is stored, and the rights of our users under UK and US law. By opting in to data collection, you agree to the practices described in this policy.

# 1. Data Collected

With the user's consent (opt-in analytics only), Homebox collects **anonymized** data, including:

* Homebox application version
* Operating System (OS) type and platform family
* Platform version
* Kernel architecture
* Virtualization system used
* General location data (country or region), as provided by our analytics tool, **Plausible**

Additionally, we collect default, anonymized data through Plausible, such as usage statistics, to understand how Homebox is used and to support its ongoing development.

# 2. Data Storage and Control

All data collected through Homebox's analytics are managed and stored in our self-hosted Plausible instance. No user data resides on third-party servers or is shared outside the control of Homebox and its administrative team (Sysadmins Media). The anonymized analytics generated from this data are publicly accessible, allowing users to review the data as we do, however Homebox will at no point share (or store) any analytical data that can be used to personally identify individual users of its systems.

tankerkiller125 marked this conversation as resolved.
Show resolved Hide resolved
# 3. Data Usage

We use the collected data exclusively to improve Homebox:

* Informing development focus based on popular platforms, architectures, and virtualization systems
* Aiding in troubleshooting and diagnostic processes for better support and stability

All data collected is aggregated and anonymized to ensure individual users cannot be identified.

# 4. Data Retention

The information remains in our self-hosted Plausible instance as long as it remains useful for improving the application, there is no set retention period for the deletion of this data, however Homebox remains dedicated to transparency and openly shares the anonymized usage data collected by our systems publicly for our users to review.

tankerkiller125 marked this conversation as resolved.
Show resolved Hide resolved
# 5. User rights and Opt-In Consent

As Homebox is operated around the world, we conform to the relevant laws as applicable in any local jurisdiction. Homebox data is stored and processed in the US, with staff residing in US and UK locations.

Under both UK and US data protection laws, users have the following rights:
tankerkiller125 marked this conversation as resolved.
Show resolved Hide resolved

* **Right to opt-in**: Data collection only begins when a user explicitly chooses to share this information.
* **Right to review**: Users can view the publicly accessible analytics to understand how their data contributes to Homebox.
* **Right to withdraw consent**: Users may opt out at any time, stopping any further data collection from their device.

# 6. Policy Changes

Any changes to this privacy policy will be communicated to users through Homebox's update channels (namely Discord or Reddit) **at a minimum** 7 full days prior to any change being conducted (unless mandated by law to do so otherwise).

Continued use of Homebox following updates will imply acceptance of the revised policy, and users are free to opt-out of analytics at any point without impact to their usage of Homebox software.


### Contact Us

For any questions about this privacy policy or your data, please contact the team through our official channels:

* Discord: https://discord.homebox.software/
* Reddit Modmail: r/Homebox
* Github: https://git.homebox.software/
48 changes: 25 additions & 23 deletions docs/en/configure-homebox.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,31 @@

## Env Variables & Configuration

| Variable | Default | Description |
| ------------------------------------ | ---------------------- | ---------------------------------------------------------------------------------- |
| HBOX_MODE | `production` | application mode used for runtime behavior can be one of: `development`, `production` |
| HBOX_WEB_PORT | 7745 | port to run the web server on, if you're using docker do not change this |
| HBOX_WEB_HOST | | host to run the web server on, if you're using docker do not change this |
| HBOX_OPTIONS_ALLOW_REGISTRATION | true | allow users to register themselves |
| HBOX_OPTIONS_AUTO_INCREMENT_ASSET_ID | true | auto-increments the asset_id field for new items |
| HBOX_OPTIONS_CURRENCY_CONFIG | | json configuration file containing additional currencie |
| HBOX_WEB_MAX_UPLOAD_SIZE | 10 | maximum file upload size supported in MB |
| HBOX_WEB_READ_TIMEOUT | 10s | Read timeout of HTTP sever |
| HBOX_WEB_WRITE_TIMEOUT | 10s | Write timeout of HTTP server |
| HBOX_WEB_IDLE_TIMEOUT | 30s | Idle timeout of HTTP server |
| HBOX_STORAGE_DATA | /data/ | path to the data directory, do not change this if you're using docker |
| HBOX_STORAGE_SQLITE_URL | /data/homebox.db?_fk=1 | sqlite database url, if you're using docker do not change this |
| HBOX_LOG_LEVEL | `info` | log level to use, can be one of `trace`, `debug`, `info`, `warn`, `error`, `critical` |
| HBOX_LOG_FORMAT | `text` | log format to use, can be one of: `text`, `json` |
| HBOX_MAILER_HOST | | email host to use, if not set no email provider will be used |
| HBOX_MAILER_PORT | 587 | email port to use |
| HBOX_MAILER_USERNAME | | email user to use |
| HBOX_MAILER_PASSWORD | | email password to use |
| HBOX_MAILER_FROM | | email from address to use |
| HBOX_SWAGGER_HOST | 7745 | swagger host to use, if not set swagger will be disabled |
| HBOX_SWAGGER_SCHEMA | `http` | swagger schema to use, can be one of: `http`, `https` |
| Variable | Default | Description |
|--------------------------------------|------------------------|----------------------------------------------------------------------------------------|
| HBOX_MODE | `production` | application mode used for runtime behavior can be one of: `development`, `production` |
| HBOX_WEB_PORT | 7745 | port to run the web server on, if you're using docker do not change this |
| HBOX_WEB_HOST | | host to run the web server on, if you're using docker do not change this |
| HBOX_OPTIONS_ALLOW_REGISTRATION | true | allow users to register themselves |
| HBOX_OPTIONS_AUTO_INCREMENT_ASSET_ID | true | auto-increments the asset_id field for new items |
| HBOX_OPTIONS_CURRENCY_CONFIG | | json configuration file containing additional currencie |
| HBOX_WEB_MAX_UPLOAD_SIZE | 10 | maximum file upload size supported in MB |
| HBOX_WEB_READ_TIMEOUT | 10s | Read timeout of HTTP sever |
| HBOX_WEB_WRITE_TIMEOUT | 10s | Write timeout of HTTP server |
| HBOX_WEB_IDLE_TIMEOUT | 30s | Idle timeout of HTTP server |
| HBOX_STORAGE_DATA | /data/ | path to the data directory, do not change this if you're using docker |
| HBOX_STORAGE_SQLITE_URL | /data/homebox.db?_fk=1 | sqlite database url, if you're using docker do not change this |
| HBOX_LOG_LEVEL | `info` | log level to use, can be one of `trace`, `debug`, `info`, `warn`, `error`, `critical` |
| HBOX_LOG_FORMAT | `text` | log format to use, can be one of: `text`, `json` |
| HBOX_MAILER_HOST | | email host to use, if not set no email provider will be used |
| HBOX_MAILER_PORT | 587 | email port to use |
| HBOX_MAILER_USERNAME | | email user to use |
| HBOX_MAILER_PASSWORD | | email password to use |
| HBOX_MAILER_FROM | | email from address to use |
| HBOX_SWAGGER_HOST | 7745 | swagger host to use, if not set swagger will be disabled |
| HBOX_SWAGGER_SCHEMA | `http` | swagger schema to use, can be one of: `http`, `https` |
| HBOX_ALLOW_ANALYTICS | `false` | Opt-In basic non-identifiable analytics to assist with optimizing Homebox. |


::: tip "CLI Arguments"
If you're deploying without docker you can use command line arguments to configure the application. Run `homebox --help` for more information.
Expand Down
6 changes: 6 additions & 0 deletions docs/en/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ $ docker run -d \
--restart unless-stopped \
--publish 3100:7745 \
--env TZ=Europe/Bucharest \
--env HBOX_ALLOW_ANALYTICS=false \
--volume /path/to/data/folder/:/data \
ghcr.io/sysadminsmedia/homebox:latest
# ghcr.io/sysadminsmedia/homebox:latest-rootless
Expand All @@ -49,6 +50,7 @@ services:
- HBOX_LOG_LEVEL=info
- HBOX_LOG_FORMAT=text
- HBOX_WEB_MAX_UPLOAD_SIZE=10
- HBOX_ALLOW_ANALYTICS=false
volumes:
- homebox-data:/data/
ports:
Expand All @@ -67,6 +69,10 @@ If you use the `rootless` image, and instead of using named volumes you would pr
If you have previously set up docker compose with the `HBOX_WEB_READ_TIMEOUT`, `HBOX_WEB_WRITE_TIMEOUT`, or `HBOX_IDLE_TIMEOUT` options, and you were previously using the hay-kot image, please note that you will have to add an `s` for seconds or `m` for minutes to the end of the integers. A dependency update removed the defaultation to seconds and it now requires an explicit duration time.
:::

::: info
Please consider setting the `HBOX_ALLOW_ANALYTICS` environment variable to `true` to help us improve Homebox. It's a strictly opt-in feature, and we do not collect any personal information or sensitive information.
:::

2. While in the same folder as docker-compose.yml, start the container by running:

```bash
Expand Down
Loading