Add more pages

This commit is contained in:
Paul Friederichsen 2021-12-23 07:53:24 -06:00
parent 6066749bee
commit ecfb361892
13 changed files with 717 additions and 29 deletions

View File

@ -74,9 +74,9 @@ Lets revisit the journal, this time with two transactions. Note that the databa
3. Write Change 2
4. Read data
5. Write Change 3
~~6. FLUSH~~
6. ~~FLUSH~~
7. End Transaction 1
~~8. FLUSH~~
8. ~~FLUSH~~
9. Begin Transaction 2
10. Write Change 2
11. Write Ch

View File

@ -1,3 +1,8 @@
:root {
--md-text-font: Roboto, ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", Ubuntu, sans-serif;
--md-code-font: "Roboto Mono", ui-monospace, Consolas, Menlo, monospace;
}
.spoiler:not(:hover) {
color: #000;
background-color: #000;
@ -5,8 +10,13 @@
.hydrus-warning {
color: #d00;
}
:root {
--md-text-font: Roboto, ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", Ubuntu, sans-serif;
--md-code-font: "Roboto Mono", ui-monospace, Consolas, Menlo, monospace;
.dealwithit {
color: #ff0000;
text-shadow:
1px 1px 0 #ff7f00,
2px 2px 0 #ffff00,
3px 3px 0 #00ff00,
4px 4px 0 #0000ff,
5px 5px 0 #6600ff,
6px 6px 0 #8b00ff;
}

View File

@ -1,14 +1,9 @@
---
hide:
- navigation
---
# Changelog
!!! note
This is the new changelog. For versions prior to 466 see the [old changelog](old_changelog.html).
## Version 467
## [Version 467](https://github.com/hydrusnetwork/hydrus/releases/tag/v467)
### new scanbar cleanup
* the media container's scanbar and volume control are now combined on the same widget, meaning they now show/hide in sync and faster. their layout calculation is also more sensible. the new controls bar also has a thin border to make it pop better against a background video
@ -43,7 +38,7 @@ hide:
* added GET /manage_database/mr_bones to the Client API. it returns a JSON Object with the same numbers used in the _help->how boned am I?_ dialog
* incremented Client API version to 23
## Version 466
## [Version 466](https://github.com/hydrusnetwork/hydrus/releases/tag/v466)
### video scanbar autohide
* the scanbar that shows below audio and video is now embedded inside the video frame, and it show/hides based on how close your mouse is to it

32
docs/contact.md Normal file
View File

@ -0,0 +1,32 @@
# contact and links
I welcome all your bug reports, questions, ideas, and comments. It is always interesting to see how other people are using my software and what they generally think of it. Most of the changes every week are suggested by users.
You can contact me by email, twitter, tumblr, discord, or the 8chan.moe /t/ thread or Endchan board--I do not mind which. Please know that I have difficulty with social media, and while I try to reply to all messages, it sometimes takes me a while to catch up.
The [Github Issue Tracker](https://github.com/hydrusnetwork/hydrus/issues) was turned off for some time, as it did not fit my workflow and I could not keep up, but it is now running again, managed by a team of volunteer users. Please feel free to submit feature requests there if you are comfortable with Github. I am not socially active on Github, please do not ping me there.
I am on the discord on Saturday afternoon, USA time, if you would like to talk live, and briefly on Wednesday after I put the release out. If that is not a good time for you, please leave me a DM and I will get to you when I can. There are also plenty of other hydrus users who idle who can help with support questions.
I delete all tweets and resolved email conversations after three months. So, if you think you are waiting for a reply, or I said I was going to work on something you care about and seem to have forgotten, please do nudge me.
I am always overwhelmed by work and behind on my messages. This is not to say that I do not enjoy just hanging out or talking about possible new features, but forgive me if some work takes longer than expected or if I cannot get to a particular idea quickly. In the same way, if you encounter actual traceback-raising errors or crashes, there is only one guy to fix it, so I prefer to know ASAP so I can prioritise.
I work by myself because I have acute difficulty working with others. Please do not spontaneously write long design documents or prepare other work for me--I find it more stressful than helpful, every time, and I won't give it the attention it deserves. If you would like to contribute time to hydrus, the user projects like the downloader repository and wiki help guides always have things to do.
That said:
* [homepage](https://hydrusnetwork.github.io/hydrus/)
* [github](https://github.com/hydrusnetwork/hydrus) ([latest build](https://github.com/hydrusnetwork/hydrus/releases/latest))
* [issue tracker](https://github.com/hydrusnetwork/hydrus/issues)
* [8chan.moe /t/ (Hydrus Network General)](https://8chan.moe/t/catalog.html) ([endchan bunker](https://endchan.net/hydrus/) [(.org)](https://endchan.org/hydrus/))
* [tumblr](https://hydrus.tumblr.com) ([rss](http://hydrus.tumblr.com/rss))
* [new downloads](https://github.com/hydrusnetwork/hydrus/releases)
* [old downloads](https://www.mediafire.com/hydrus)
* [twitter](https://twitter.com/hydrusnetwork)
* [email](mailto:hydrus.admin@gmail.com)
* [discord](https://discord.gg/wPHPCUZ)
* [patreon](https://www.patreon.com/hydrus_dev)
* [user-run repository and wiki (including download presets for several non-default boorus)](https://github.com/CuddleBear92/Hydrus-Presets-and-Scripts)

108
docs/faq.md Normal file
View File

@ -0,0 +1,108 @@
# FAQ
## what is a repository? { id="repositories" }
A _repository_ is a service in the hydrus network that stores a certain kind of information--files or tag mappings, for instance--as submitted by users all over the internet. Those users periodically synchronise with the repository so they know everything that it stores. Sometimes, like with tags, this means creating a complete local copy of everything on the repository. Hydrus network clients never send queries to repositories; they perform queries over their local cache of the repository's data, keeping everything confined to the same computer.
## what is a tag? { id="tags" }
[wiki](https://en.wikipedia.org/wiki/Tag_(metadata))
A _tag_ is a small bit of text describing a single property of something. They make searching easy. Good examples are "flower" or "nicolas cage" or "the sopranos" or "2003". By combining several tags together ( e.g. \[ 'tiger woods', 'sports illustrated', '2008' \] or \[ 'cosplay', 'the legend of zelda' \] ), a huge image collection is reduced to a tiny and easy-to-digest sample.
A good word for the connection of a particular tag to a particular file is _mapping_.
Hydrus is designed with the intention that tags are for _searching_, not _describing_. Workflows and UI are tuned for finding files and other similar files (e.g. by the same artist), and while it is possible to have nice metadata overlays around files, this is not considered their chief purpose. Trying to have 'perfect' descriptions for files is often a rabbit-hole that can consume hours of work with relatively little demonstrable benefit.
All tags are automatically converted to lower case. 'Sunset Drive' becomes 'sunset drive'. Why?
1. Although it is more beautiful to have 'The Lord of the Rings' rather than 'the lord of the rings', there are many, many special cases where style guides differ on which words to capitalise.
2. As 'The Lord of the Rings' and 'the lord of the rings' are semantically identical, it is natural to search in a case insensitive way. When case does not matter, what point is there in recording it?
Furthermore, leading and trailing whitespace is removed, and multiple whitespace is collapsed to a single character.
' yellow dress '
becomes
'yellow dress'
## what is a namespace? { id="namespaces" }
A _namespace_ is a category that in hydrus prefixes a tag. An example is 'person' in the tag 'person:ron paul'--it lets people and software know that 'ron paul' is a name. You can create any namespace you like; just type one or more words and then a colon, and then the next string of text will have that namespace.
The hydrus client gives namespaces different colours so you can pick out important tags more easily in a large list, and you can also search by a particular namespace, even creating complicated predicates like 'give all files that do not have any character tags', for instance.
## why not use filenames and folders? { id="filenames" }
As a retrieval method, filenames and folders are less and less useful as the number of files increases. Why?
* A filename is not unique; did you mean this "04.jpg" or _this_ "04.jpg" in another folder? Perhaps "04 (3).jpg"?
* A filename is not guaranteed to describe the file correctly, e.g. hello.jpg
* A filename is not guaranteed to stay the same, meaning other programs cannot rely on the filename address being valid or even returning the same data every time.
* A filename is often--for _ridiculous_ reasons--limited to a certain prohibitive character set. Even when utf-8 is supported, some arbitrary ascii characters are usually not, and different localisations, operating systems and formatting conventions only make it worse.
* Folders can offer context, but they are clunky and time-consuming to change. If you put each chapter of a comic in a different folder, for instance, reading several volumes in one sitting can be a pain. Nesting many folders adds navigation-latency and tends to induce less informative "04.jpg"-type filenames.
So, the client tracks files by their _hash_. This technical identifier easily eliminates duplicates and permits the database to robustly attach other metadata like tags and ratings and known urls and notes and everything else, even across multiple clients and even if a file is deleted and later imported.
As a general rule, I suggest you not set up hydrus to parse and display all your imported files' filenames as tags. 'image.jpg' is useless as a tag. [Shed the concept of filenames as you would chains.](https://www.youtube.com/watch?v=_yYS0ZZdsnA)
## can the client manage files from their original locations? { id="external_files" }
When the client imports a file, it makes a quickly accessible but human-ugly copy in its internal database, by default under _install\_dir/db/client\_files_. When it needs to access that file again, it always knows where it is, and it can be confident it is what it expects it to be. It never accesses the original again.
This storage method is not always convenient, particularly for those who are hesitant about converting to using hydrus completely and also do not want to maintain two large copies of their collections. The question comes up--"can hydrus track files from their original locations, without having to copy them into the db?"
The technical answer is, "This support could be added," but I have decided not to, mainly because:
* Files stored in locations outside of hydrus's responsibility can change or go missing (particularly if a whole parent folder is moved!), which erodes the assumptions it makes about file access, meaning additional checks would have to be added before important operations, often with no simple recovery.
* External duplicates would not be merged, and the file system would have to be extended to handle pointless 1->n hash->path relationships.
* Many regular operations--like figuring out whether orphaned files should be physically deleted--are less simple.
* Backing up or restoring a distributed external file system is much more complicated.
* It would require more code to maintain and would mean a laggier db and interface.
* Hydrus is an attempt to get _away_ from files and folders--if a collection is too large and complicated to manage using explorer, what's the point in supporting that old system?
It is not unusual for new users who ask for this feature to find their feelings change after getting more experience with the software. If desired, path text can be preserved as tags using regexes during import, and getting into the swing of searching by metadata rather than navigating folders often shows how very effective the former is over the latter. Most users eventually import most or all of their collection into hydrus permanently, deleting their old folder structure as they go.
For this reason, if you are hesitant about doing things the hydrus way, I advise you try running it on a smaller subset of your collection, say 5,000 files, leaving the original copies completely intact. After a month or two, think about how often you used hydrus to look at the files versus navigating through folders. If you barely used the folders, you probably do not need them any more, but if you used them a lot, then hydrus might not be for you, or it might only be for some sorts of files in your collection.
## why use sqlite? { id="sqlite" }
Hydrus uses SQLite for its database engine. Some users who have experience with other engines such as MySQL or PostgreSQL sometimes suggest them as alternatives. SQLite serves hydrus's needs well, and at the moment, there are no plans to change.
Since this question has come up frequently, a user has written an excellent document talking about the reasons to stick with SQLite. If you are interested in this subject, please check it out here:
[https://gitgud.io/prkc/hydrus-why-sqlite/blob/master/README.md](https://gitgud.io/prkc/hydrus-why-sqlite/blob/master/README.md)
## what is a hash? { id="hashes" }
[wiki](https://en.wikipedia.org/wiki/Hash_function)
Hashes are a subject you usually have to be a software engineer to find interesting. The simple answer is that they are unique names for things. Hashes make excellent identifiers inside software, as you can safely assume that f099b5823f4e36a4bd6562812582f60e49e818cf445902b504b5533c6a5dad94 refers to one particular file and no other. In the client's normal operation, you will never encounter a file's hash. If you want to see a thumbnail bigger, double-click it; the software handles the mathematics.
_For those who_ are _interested: hydrus uses SHA-256, which spits out 32-byte (256-bit) hashes. The software stores the hash densely, as 32 bytes, only encoding it to 64 hex characters when the user views it or copies to clipboard. SHA-256 is not perfect, but it is a great compromise candidate; it is secure for now, it is reasonably fast, it is available for most programming languages, and newer CPUs perform it more efficiently all the time._
## what is an access key? { id="access_keys" }
The hydrus network's repositories do not use username/password, but instead a single strong identifier-password like this:
_7ce4dbf18f7af8b420ee942bae42030aab344e91dc0e839260fcd71a4c9879e3_
These hex numbers give you access to a particular account on a particular repository, and are often combined like so:
_7ce4dbf18f7af8b420ee942bae42030aab344e91dc0e839260fcd71a4c9879e3@hostname.com:45871_
They are long enough to be impossible to guess, and also randomly generated, so they reveal nothing personally identifying about you. Many people can use the same access key (and hence the same account) on a repository without consequence, although they will have to share any bandwidth limits, and if one person screws around and gets the account banned, everyone will lose access.
The access key is the account. Do not give it to anyone you do not want to have access to the account. An administrator will never need it; instead they will want your _account id_.
## what is an account id? { id="account_ids" }
This is another long string of random hexadecimal that _identifies_ your account without giving away access. If you need to identify yourself to a repository administrator (say, to get your account's permissions modified), you will need to tell them your account id. You can copy it to your clipboard in _services->review services_.
## why can my friend not see what I just uploaded? { id="delays" }
The repositories do not work like conventional search engines; it takes a short but predictable while for changes to propagate to other users.
The client's searches only ever happen over its local cache of what is on the repository. Any changes you make will be delayed for others until their next update occurs. At the moment, the update period is 100,000 seconds, which is about 1 day and 4 hours.

91
docs/ipfs.md Normal file
View File

@ -0,0 +1,91 @@
---
title: IPFS
---
IPFS is a p2p protocol that makes it easy to share many sorts of data. The hydrus client can communicate with an IPFS daemon to send and receive files.
You can read more about IPFS from [their homepage](http://ipfs.io), or [this guide](https://medium.com/@ConsenSys/an-introduction-to-ipfs-9bba4860abd0) that explains its various rules in more detail.
For our purposes, we only need to know about these concepts:
* **IPFS daemon** \-\- A running instance of the IPFS executable that can talk to the larger network.
* **IPFS multihash** \-\- An IPFS-specific identifier for a file or group of files.
* **pin** \-\- To tell our IPFS daemon to host a file or group of files.
* **unpin** \-\- To tell our IPFS daemon to stop hosting a file or group of files.
## getting ipfs { id="getting_ipfs" }
_Note there is now a nicer desktop package [here](https://docs.ipfs.io/install/ipfs-desktop/). I haven't used it, but it may be a nicer intro to the program._
Get the prebuilt executable [here](https://docs.ipfs.io/install/command-line/). Inside should be a very simple 'ipfs' executable that does everything. Extract it somewhere and open up a terminal in the same folder, and then type:
* `ipfs init`
* `ipfs daemon`
The IPFS exe should now be running in that terminal, ready to respond to requests:
![](images/ipfs_terminal.png)
You can kill it with ++ctrl+c++ and restart it with the `ipfs daemon` call again (you only have to run `ipfs init` once).
When it is running, opening [this page](http://127.0.0.1:8080/ipfs/QmfM2r8seH2GiRaC4esTjeraXEachRt8ZsSeGaWTPLyMoG) should download and display an example 'Hello World!' file from <span class="dealwithit">\~\~\~across the internet\~\~\~</span>.
Your daemon listens for other instances of ipfs using port 4001, so if you know how to open that port in your firewall and router, make sure you do.
## connecting your client { id="connecting" }
IPFS daemons are treated as services inside hydrus, so go to _services->manage services->remote->ipfs daemons_ and add in your information. Hydrus uses the API port, default 5001, so you will probably want to use credentials of `127.0.0.1:5001`. You can click 'test credentials' to make sure everything is working.
![](images/ipfs_services.png)
Thereafter, you will get the option to 'pin' and 'unpin' from a thumbnail's right-click menu, like so:
![](images/ipfs_pin.png)
This works like hydrus's repository uploads--it won't happen immediately, but instead will be queued up at the pending menu. Commit all your pins when you are ready:
![](images/ipfs_commit.png)
Notice how the IPFS icon appears on your pending and pinned files. You can search for these files using 'system:file service'.
Unpin works the same as pin, just like a hydrus repository petition.
Right-clicking any pinned file will give you a new 'share' action:
![](images/ipfs_multihash.png)
Which will put it straight in your clipboard. In this case, it is [QmP6BNvWfkNf74bY3q1ohtDZ9gAmss4LAjuFhqpDPQNm1S](http://127.0.0.1:8080/ipfs/QmP6BNvWfkNf74bY3q1ohtDZ9gAmss4LAjuFhqpDPQNm1S).
If you want to share a pinned file with someone, you have to tell them this multihash. They can then:
* View it through their own ipfs daemon's gateway, at `http://127.0.0.1:8080/ipfs/[multihash]`
* View it through a public web gateway, such as the one the IPFS people run, at `http://ipfs.io/ipfs/[multihash]`
* Download it through their ipfs-connected hydrus client by going _pages->new download popup->an ipfs multihash_.
## directories { id="directories" }
If you have many files to share, IPFS also supports directories, and now hydrus does as well. IPFS directories use the same sorts of multihash as files, and you can download them into the hydrus client using the same _pages->new download popup->an ipfs multihash_ menu entry. The client will detect the multihash represents a directory and give you a simple selection dialog:
![](images/ipfs_dir_download.png)
You may recognise those hash filenames--this example was created by hydrus, which can create ipfs directories from any selection of files from the same right-click menu:
![](images/ipfs_dir_upload.png)
Hydrus will pin all the files and then wrap them in a directory, showing its progress in a popup. Your current directory shares are summarised on the respective _services->review services_ panel:
![](images/ipfs_review_services.png)
## additional links { id="additional_links" }
If you find you use IPFS a lot, here are some add-ons for your web browser, as recommended by /tech/:
This script changes all bare ipfs hashes into clickable links to the ipfs gateway (on page loads):
- [https://greasyfork.org/en/scripts/14837-ipfs-hash-linker](https://greasyfork.org/en/scripts/14837-ipfs-hash-linker)
These redirect all gateway links to your local daemon when it's on, it works well with the previous script:
- [https://github.com/lidel/ipfs-firefox-addon](https://github.com/lidel/ipfs-firefox-addon)
- [https://github.com/dylanPowers/ipfs-chrome-extension](https://github.com/dylanPowers/ipfs-chrome-extension)

64
docs/local_booru.md Normal file
View File

@ -0,0 +1,64 @@
# local booru
!!! warning
This was a fun project, but it never advanced beyond a prototype. The future of this system is other people's nice applications plugging into the [Client API](client_api.html).
The hydrus client has a simple booru to help you share your files with others over the internet.
First of all, this is **hosted from your client**, which means other people will be connecting to your computer and fetching files you choose to share from your hard drive. If you close your client or shut your computer down, the local booru will no longer work.
## how to do it { id="setting_up" }
First of all, turn the local booru server on by going to _services->manage services_ and giving it a port:
![](images/local_booru_services.png)
It doesn't matter what you pick, but make it something fairly high. When you ok that dialog, the client should start the booru. You may get a firewall warning.
Then right click some files you want to share and select _share->local booru_. This will throw up a small dialog, like so:
![](images/local_booru_dialog.png)
This lets you enter an optional _name_, which titles the share and helps you keep track of it, an optional _text_, which lets you say some words or html to the people you are sharing with, and an _expiry_, which lets you determine if and when the share will no longer work.
You can also copy either the internal or external link to your clipboard. The internal link (usually starting something like `http://127.0.0.1:45866/`) works inside your network and is great just for testing, while the external link (starting `http://[your external ip address]:[external port]/`) will work for anyone around the world, **as long as your booru's port is being forwarded correctly**.
If you use a dynamic-ip service like [No-IP](https://www.noip.com/), you can replace your external IP with your redirect hostname. You have to do it by hand right now, but I'll add a way to do it automatically in future.
!!! danger
Note that anyone with the external link will be able to see your share, so make sure you only share links with people you trust.
## forwarding your port { id="port_forwarding" }
Your home router acts as a barrier between the computers inside the network and the internet. Those inside can see out, but outsiders can only see what you tell the router to permit. Since you want to let people connect to your computer, you need to tell the router to forward all requests of a certain kind to your computer, and thus your client.
If you have never done this before, it can be a headache, especially doing it manually. Luckily, a technology called UPnP makes it a ton easier, and this is how your Skype or Bittorrent clients do it automatically. Not all routers support it, but most do. You can have hydrus try to open a port this way back on _services->manage services_. Unless you know what you are doing and have a good reason to make them different, you might as well keep the internal and external ports the same.
Once you have it set up, the client will try to make sure your router keeps that port open for your client. If it all works, you should see the new mapping appear in your _services->manage local upnp_ dialog, which lists all your router's current port mappings.
If you want to test that the port forward is set up correctly, going to `http://[external ip]:[external port]/` should give a little html just saying hello. Your ISP might not allow you to talk to yourself, though, so ask a friend to try if you are having trouble.
If you still do not understand what is going on here, [this](http://www.howtogeek.com/66214/how-to-forward-ports-on-your-router/) is a good article explaining everything.
If you do not like UPnP or your router does not support it, you can set the port forward up manually, but I encourage you to keep the internal and external port the same, because absent a 'upnp port' option, the 'copy external share link' button will use the internal port.
## so, what do you get? { id="example" }
The html layout is very simple:
* * *
![](images/local_booru_html.png)
* * *
It uses a very similar stylesheet to these help pages. If you would like to change the style, have a look at the html and then edit install\_dir/static/local\_booru_style.css. The thumbnails will be the same size as in your client.
## editing an existing share { id="editing_shares" }
You can review all your shares on _services->review services_, under _local->booru_. You can copy the links again, change the title/text/expiration, and delete any shares you don't want any more.
## future plans { id="future" }
This was a fun project, but it never advanced beyond a prototype. The future of this system is other people's nice applications plugging into the [Client API](client_api.html).

136
docs/privacy.md Normal file
View File

@ -0,0 +1,136 @@
# Privacy
!!! tldr "tl;dr"
Using a trustworthy VPN for all your remotely fun internet traffic is a good idea. It is cheap and easy these days, and it offers multiple levels of general protection.
I have tried very hard to ensure the hydrus network servers respect your privacy. They do not work like normal websites, and the amount of information your client will reveal to them is very limited. For most general purposes, normal users can rest assured that their activity on a repository like the Public Tag Repository (PTR) is effectively completely anonymous.
You need an account to connect, but all that really means serverside is a random number with a random passcode. Your client tells nothing more to the server than the exact content you upload to it (e.g. tag mappings, which are a tag+file_hash pair). The server cannot help but be aware of your IP address to accept your network request, but in all but one situation--uploading a file to a file repository when the administrator has set to save IPs for DMCA purposes--it forgets your IP as soon as the job is done.
So that janitors can process petitions efficiently and correct mistakes, servers remember which accounts upload which content, but they do not communicate this to any place, and the memory only lasts for a certain time--after which the content is completely anonymised. The main potential privacy worries are over a malicious janitor or--more realistically, since the janitor UI is even more buggy and feature-poor than the hydrus front-end!--a malicious server owner or anyone else who gains raw access to the server's raw database files or its code as it operates. Even in the case where you cannot trust the server you are talking to, hydrus should be _fairly_ robust, simply because the client does not say much to the server, nor that often. The only realistic worries, as I talk about in detail below, are if you actually upload personal files or tag personal files with real names. I can't do much about being Anon if you (accidentally or not), declare who you are.
So, in general, if you are on a good VPN and tagging anime babes from boorus, I think we are near perfect on privacy. That said, our community is rightly constantly thinking about this topic, so in the following I have tried to go into exhaustive detail. Some of the vulnerabilities are impractical and esoteric, but if nothing else it is fun to think about. If you can think of more problems, or decent mitigations, let me know!
## https certificates { id="https_certificates" }
Hydrus servers only communicate in https, so anyone who is able to casually observe your traffic (say your roommate cracked your router, or the guy running the coffee shop whose wifi you are using likes to snoop) should not ever be able to see what data you are sending or receiving. If you do not use a VPN, they will be able to see that you _are_ talking to the repository (and the repository will technically see who you are, too, though as above, it normally isn't interested). Someone more powerful, like your ISP or Government, may be able to do more:
**If you just start a new server yourself**
:
When you first make a server, the 'certificate' it creates to enable https is a low quality one. It is called 'self-signed' because it is only endorsed by itself and it is not tied to a particular domain on the internet that everyone agrees on via DNS. Your traffic to this server is still encrypted, but an advanced attacker who stands between you and the server could potentially perform what is called a man-in-the-middle attack and see your traffic.
This problem is fairly mitigated by using a VPN, since even if someone were able to MitM your connection, they know no more than your VPN's location, not your IP.
_A future version of the network will further mitigate this problem by having you enter unverified certificates into a certificate manager and then compare to that store on future requests, to try to detect if a MitM attack is occurring._
**If the server is on a domain and now uses a proper verified certificate**
:
If the admin hosts the server on a website domain (rather than a raw IP address) and gets a proper certificate for that domain from a service like Let's Encrypt, they can swap that into the server and then your traffic should be protected from any eavesdropper. It is still good to use a VPN to further obscure _who_ you are, including from the server admin.
You can check how good a server's certificate is by loading its base address in the form `https://host:port` into your browser. If it has a nice certificate--like the [PTR](https://ptr.hydrus.network:45871/)--the welcome page will load instantly. If it is still on self-signed, you'll get one of those 'can't show this page unless you make an exception' browser error pages before it will show.
## accounts { id="accounts" }
An account has two hex strings, like this:
* **Access key: `4a285629721ca442541ef2c15ea17d1f7f7578b0c3f4f5f2a05f8f0ab297786f`**
This is in your _services->manage services_ panel, and acts like a password. Keep this absolutely secret--only you know it, and no one else ever needs to. If the server has not had its code changed, it does not actually know this string, but it is stores special data that lets it _verify_ it when you 'log in'.
* **Account ID: `207d592682a7962564d52d2480f05e72a272443017553cedbd8af0fecc7b6e0a`**
This can be copied from a button in your _services->review services_ panel, and acts a bit like a semi-private username. Only janitors should ever have access to this. If you ever want to contact the server admin about an account upgrade or similar, they will need to know this so they can load up your account and alter it.
When you generate a new account, the client first asks the server for a list of available auto-creatable account types, then asks for a registration token for one of them, then uses the token to generate an access key. The server is never told anything about you, and it forgets your IP address as soon as it finishes talking to you.
Your account also stores a bandwidth use record and some miscellaneous data such as when the account was created, if and when it expires, what permissions and bandwidth rules it has, an aggregate score of how often it has petitions approved rather than denied, and whether it is currently banned. I do not think someone inspecting the bandwidth record could figure out what you were doing based on byte counts (especially as with every new month the old month's bandwidth records are compressed to just one number) beyond the rough time you synced and whether you have done much uploading. Since only a janitor can see your account and could feasibly attempt to inspect bandwidth data, they would already know this information.
## downloading { id="downloading" }
When you sync with a repository, your client will download and then keep up to date with all the metadata the server knows. This metadata is downloaded the same way by all users, and it comes in a completely anonymous format. The server does not know what you are interested in, and no one who downloads knows who uploaded what. Since the client regularly updates, a detailed analysis of the raw update files will reveal roughly when a tag or other row was added or deleted, although that timestamp is no more precise than the duration of the update period (by default, 100,000 seconds, or a little over a day).
Your client will never ask the server for information about a particular file or tag. You download everything in generic chunks, form a local index of that information, and then all queries are performed on your own hard drive with your own CPU.
By just downloading, even if the server owner were to identify you by your IP address, all they know is that you sync. They cannot tell anything about your files.
In the case of a file repository, you client downloads all the thumbnails automatically, but then you download actual files separately as you like. The server does not log which files you download.
## uploading { id="uploading" }
When you upload, your account is temporarily linked to the rows of content you add. This is so janitors can group petitions by who makes them, undo large mistakes easily, and even leave you a brief message (like "please stop adding those clothing siblings") for your client to pick up the next time it syncs your account. After the temporary period is over, all submissions are anonymised. So, what are the privacy concerns with that? Isn't the account 'Anon'?
[Privacy can be tricky](https://en.wikipedia.org/wiki/AOL_search_data_leak). Hydrus tech is obviously far, far better than anything normal consumers use, but here I believe are the remaining barriers to pure Anonymity, assuming someone with resources was willing to put a lot of work in to attack you:
!!! note
I am using the PTR as the example since that is what most people are using. If you are uploading to a server run between friends, privacy is obviously more difficult to preserve--if there are only three users, it may not be too hard to figure out who is uploading the NarutoXSonichu diaperfur content! If you are talking to a server with a small group of users, don't upload anything crazy or personally identifying unless that's the point of the server.
* #### IP Address Across Network
_Attacker:_ ISP/Government.
_Exposure:_ That you use the PTR.
_Problem:_ Your IP address may be recorded by servers in between you and the PTR (e.g. your ISP/Government). Anyone who could convert that IP address and timestamp into your identity would know you were a PTR user.
_Mitigation:_ Use a trustworthy VPN.
* #### IP Address At PTR
_Attacker:_ PTR administrator or someone else who has access to the server as it runs.
_Exposure:_ Which PTR account you are.
_Problem:_ I may be lying to you about the server forgetting IPs, or the admin running the PTR may have secretly altered its code. If the malicious admin were able to convert IP address and timestamp into your identity, they obviously be able to link that to your account and thus its various submissions.
_Mitigation:_ Use a trustworthy VPN.
* #### Time Identifiable Uploads
_Attacker:_ Anyone with an account on the PTR.
_Exposure:_ That you use the PTR.
_Problem:_ If a tag was added way before the file was public, then it is likely the original owner tagged it. An example would be if you were an artist and you tagged your own work on the PTR two weeks before publishing the work. Anyone who looked through the server updates carefully and compared to file publish dates, particularly if they were targeting you already, could notice the date discrepancy and know you were a PTR user.
_Mitigation:_ Don't tag any file you plan to share if you are currently the only person who has any copies. Upload it, then tag it.
* #### Content Identifiable Uploads
_Attacker:_ Anyone with an account on the PTR.
_Exposure:_ That you use the PTR.
_Problem:_ All uploads are shared anonymously with other users, but if the content itself is identifying, you may be exposed. An example would be if there was some popular lewd file floating around of you and your girlfriend, but no one knew who was in it. If you decided to tag it with accurate 'person:' tags, anyone synced with the PTR, when they next looked at that file, would see those person tags. The same would apply if the file was originally private but then leaked.
_Mitigation:_ Just like an imageboard, do not upload any personally identifying information.
* #### Individual Account Cross-referencing
_Attacker:_ PTR administrator or someone else with access to the server database files after one of your uploads has been connected to your real identity, perhaps with a Time/Content Identifiable Upload as above.
_Exposure:_ What you have been uploading recently.
_Problem:_ If you accidentally tie your identity to an individual content row (could be as simple as telling an admin 'yes, I, person whose name you know, uploaded that sibling last week'), then anyone who can see which accounts uploaded what will obviously be able to see your other uploads.
_Mitigation:_ Best practise is to not to reveal specifically what you upload. **Note that this vulnerability (an admin looking up what else you uploaded after they discover something else you did) is now well mitigated by the account history anonymisation as below (assuming the admin has not altered the code to disable it!). If the server is set to anonymise content after 90 days, then your account can only be identified from specific content rows that were uploaded in the past 90 days, and cross-references would also only see the last 90 days of activity.**
* #### Big Brain Individual Account Mapping Fingerprint Cross-referencing
_Attacker:_ Someone who has access to tag/file favourite lists on another site and gets access to a hydrus repository that has been compromised to not anonymise history for a long duration.
_Exposure:_ Which PTR account another website's account uses.
_Problem:_ Someone who had raw access to the PTR database's historical account record (i.e. they had disabled the anonymisation routine below) and also had compiled some booru users' 'favourite tag/artist' lists and was very clever could try to cross reference those two lists and connect a particular PTR account to a particular booru account based on similar tag distributions. There would be many holes in the PTR record, since only the first account to upload a tag mapping is linked to it, but maybe it would be possible to get high confidence on a match if you have really distinct tastes. Favourites lists are probably decent digital fingerprints, and there may be a shadow of that in your PTR uploads, although I also think there are enough users uploading and 'competing' for saved records on different tags that each users' shadow would be too indistinct to really pull this off.
_Mitigation:_ I am mostly memeing here. But privacy is tricky, and who knows what the scrapers of the future are going to do with all the cloud data they are sucking up. **Even then, the historical anonymisation routine below now generally eliminates this threat**, assuming the server has not been compromised to disable it, so it matters far less if its database files fall into bad hands in the future, but accounts on regular websites are already being aggregated by the big marketing engines, and this will only happen in more clever ways in future. I wouldn't be surprised if booru accounts are soon being connected to other online identities based on fingerprint profiles of likes and similar. Don't save your spicy favourites on a website, even if that list is private, since if that site gets hacked or just bought out one day, someone really smart could start connecting dots ten years from now.
## account history anonymisation { id="account_history" }
As the PTR moved to multiple accounts, we talked more about the potential account cross-referencing worries. The threats are marginal today, but it may be a real problem in future. If the server database files were to ever fall into bad hands, having a years-old record of who uploaded what is not excellent. Like the AOL search leak, that data may have unpleasant rammifications, especially to an intelligent scraper in the future. This historical record is also not needed for most janitorial work.
Therefore, hydrus repositories now completely anonymise all uploads after a certain delay. It works by assigning ownership of every file, mapping, or tag sibling/parent to a special 'null' account, so all trace that your account uploaded any of it is deleted. It happens by default 90 days after the content is uploaded, but it can be more or less depending on the local admin and janitors. You can see the current 'anonymisation' period under _review services_.
If you are a janitor with the ability to modify accounts based on uploaded content, you will see anything old will bring up the null account. It is specially labelled, so you can't miss it. You cannot ban or otherwise alter this account. No one can actually use it.

120
docs/running_from_source.md Normal file
View File

@ -0,0 +1,120 @@
---
title: running from source
---
I write the client and server entirely in [python](https://python.org), which can run straight from source. It is not simple to get hydrus running this way, but if none of the built packages work for you (for instance you use a non-Ubuntu-compatible flavour of Linux), it may be the only way you can get the program to run. Also, if you have a general interest in exploring the code or wish to otherwise modify the program, you will obviously need to do this.
## a quick note about Linux flavours { id="linux_flavours" }
I often point people here when they are running non-Ubuntu flavours of Linux and cannot run the build. One Debian user mentioned that he had an error like this:
```
_ImportError: /home/user/hydrus/libX11.so.6: undefined symbol: xcb\_poll\_for_reply64_
```
But that by simply deleting the _libX11.so.6_ file in the hydrus install directory, he was able to boot. I presume this meant the build was then relying on his local libX11.so, which happened to have better API compatibility. If you receive a similar error, you might like to try the same sort of thing. Let me know if you discover anything!
## building packages on windows { id="windows_build" }
Installing some packages on windows with pip may need Visual Studio's C++ Build Tools for your version of python. Although these tools are free, it can be a pain to get them through the official (and often huge) downloader installer from Microsoft. Instead, install [Chocolatey](https://chocolatey.org/) and use this one simple line:
```
choco install -y vcbuildtools visualstudio2017buildtools
```
Trust me, just do this, it will save a ton of headaches!
This can also be helpful for Windows 10 python work generally:
```
choco install -y windows-sdk-10.0
```
## what you will need { id="what_you_need" }
You will need basic python experience, python 3.x and a number of python modules, all through pip.
First of all, get the actual program. The github repo is [https://github.com/hydrusnetwork/hydrus](https://github.com/hydrusnetwork/hydrus). If you are familiar with git, you can just clone the repo to the location you want, but if not, then just go to the [latest release](https://github.com/hydrusnetwork/hydrus/releases/latest) and download and extract the source code .zip or .tar.gz somewhere. The same database location rules apply for the source release as the builds, so if you are not planning to redirect the database with the -d launch parameter, make sure the directory has write permissions (e.g. in Windows, don't put it in "Program Files")
Inside the extract should be client.py, client.pyw, and server.py. You will be treating these basically the same as the 'client' and 'server' executables--you should be able to launch them the same way and they take the same launch parameters as the exes. On Windows, using client.pyw allows you to neatly launch the program without a command terminal appearing behind it, but both the .py and .pyw work fundamentally the same--feel free to play with them both.
Hydrus needs a whole bunch of libraries, so let's now set your python up. If you are on Linux or macOS, or if you are on Windows and have an existing python you do not want to stomp all over with new modules, I recommend you create a virtual environment:
_Note, if you are on Linux, it may be easier to use your package manager instead of messing around with venv. A user has written a great summary with all needed packages [here](running_from_source_linux_packages.txt)._
To create a new venv environment:
* (navigate to your hydrus extract folder in a terminal)
* ```pip3 install virtualenv``` (if you need it)
* `pip3 install wheel` (if you need it)
* `mkdir venv`
* `virtualenv --python=python3 venv`
* `. venv/bin/activate`
That `. venv/bin/activate` line turns your venv on, which is an isolated copy of python that you can install modules to without worrying about breaking something system-wide, and will be needed every time you run the `client.pyw`/`server.py` files. You should see your terminal note you are now in the venv. You can easily tuck this venv activation into a launch script.
On Windows Powershell, the command is `.\venv\Scripts\activate`, but you may find the whole deal is done much easier in cmd than Powershell. When in Powershell, just type `cmd` to get an old fashioned command line. In cmd, the launch command is just `venv\scripts\activate`, no leading period.
After that, you can use pip to install everything you need from the appropriate requirements.txt in the base install directory. For instance, for Windows, you would go:
```
pip3 install -r requirements_windows.txt
```
If you prefer to do things manually, inspect the document and install the modules yourself.
## PyQt5 support { id="pyqt5" }
For Qt, either PySide2 (default) or PyQt5 are supported, through qtpy. For PyQt5, go:
```
pip3 install qtpy PyQtChart PyQt5
```
## FFMPEG { id="ffmpeg" }
If you don't have FFMPEG in your PATH and you want to import anything more fun than jpegs, you will need to put a static [FFMPEG](https://ffmpeg.org/) executable in your PATH or the `install_dir/bin` directory. If you can't find a static exe on Windows, you can copy the exe from one of my extractable releases.
## mpv support { id="mpv" }
MPV is optional and complicated, but it is great, so it is worth the time to figure out!
As well as the python wrapper, 'python-mpv' as in the requirements.txt, you also need the underlying library. This is _not_ mpv the program, but 'libmpv', often called 'libmpv1'.
For Windows, the dll builds are [here](https://sourceforge.net/projects/mpv-player-windows/files/libmpv/), although getting the right version for the current wrapper can be difficult (you will get errors when you try to load video if it is not correct). Just put it in your hydrus base install directory. You can also just grab the 'mpv-1.dll' I bundle in my release. In my experience, [this](https://sourceforge.net/projects/mpv-player-windows/files/libmpv/mpv-dev-x86_64-20210228-git-d1be8bb.7z/download) works with python-mpv 0.5.2.
If you are on Linux/macOS, you can usually get 'libmpv1' with _apt_. You might have to adjust your python-mpv version (e.g. `pip3 install python-mpv==0.4.5`) to get it to work.
## SQLite { id="sqlite" }
If you can, update python's SQLite--it'll improve performance.
On Windows, get the 64-bit sqlite3.dll [here](https://www.sqlite.org/download.html), and just drop it in `C:\Python37\DLLs` or wherever you have python installed. You'll be overwriting the old file, so make a backup if you want to (I have never had trouble updating like this, however).
I don't know how to do it for Linux or macOS, so if you do, please let me know!
## additional windows info { id="additional_windows" }
This may not matter any more, but in the old days, Windows pip could have problems building modules like lz4 and lxml. [This page](http://www.lfd.uci.edu/~gohlke/pythonlibs/) has a lot of prebuilt binaries--I have found it very helpful many times.
I have a fair bit of experience with Windows python, so send me a mail if you need help.
## running it { id="running_it" }
Once you have everything set up, client.pyw and server.py should look for and run off client.db and server.db just like the executables. They will look in the 'db' directory by default, or anywhere you point them with the "-d" parameter, again just like the executables. Explictly, you will be entering something like this in the terminal:
```
. venv/bin/activate
./client.py -d="/path/to/database"
```
Again, you may want to set up a shortcut to a script to make it easy.
I develop hydrus on and am most experienced with Windows, so the program is more stable and reasonable on that. I do not have as much experience with Linux or macOS, but I still appreciate and will work on your Linux/macOS bug reports.
## my code { id="my_code" }
My coding style is unusual and unprofessional. Everything is pretty much hacked together. If you are interested in how things work, please do look through the source and ask me if you don't understand something.
I'm constantly throwing new code together and then cleaning and overhauling it down the line. I work strictly alone, however, so while I am very interested in detailed bug reports or suggestions for good libraries to use, I am not looking for pull requests or suggestions on style. I know a lot of things are a mess. Everything I do is [WTFPL](https://github.com/sirkris/WTFPL/blob/master/WTFPL.md), so feel free to fork and play around with things on your end as much as you like.

78
docs/server.md Normal file
View File

@ -0,0 +1,78 @@
---
title: running your own server
---
!!! note
**You do not need the server to do anything with hydrus! It is only for advanced users to do very specific jobs!** The server is also hacked-together and quite technical. It requires a fair amount of experience with the client and its concepts, and it does not operate on a timescale that works well on a LAN. Only try running your own server once you have a bit of experience synchronising with something like the PTR and you think, 'Hey, I know exactly what that does, and I would like one!'
**[Here is a document put together by a user describing whether you want the server.](https://github.com/Zweibach/text/blob/master/Hydrus/youDontWantTheServer.md)**
## setting up a server { id="intro" }
I will use two terms, _server_ and _service_, to mean two distinct things:
* A **server** is an instantiation of the hydrus server executable (e.g. server.exe in Windows). It has a complicated and flexible database that can run many different services in parallel.
* A **service** sits on a port (e.g. 45871) and responds to certain http requests (e.g. `/file` or `/update`) that the hydrus client can plug into. A service might be a repository for a certain kind of data, the administration interface to manage what services run on a server, or anything else.
Setting up a hydrus server is easy compared to, say, Apache. There are no .conf files to mess about with, and everything is controlled through the client. When started, the server will place an icon in your system tray in Windows or open a small frame in Linux or macOS. To close the server, either right-click the system tray icon and select exit, or just close the frame.
The basic process for setting up a server is:
* Start the server.
* Set up your client with its address and initialise the admin account
* Set the server's options and services.
* Make some accounts for your users.
* ???
* Profit
Let's look at these steps in more detail:
## start the server { id="start" }
Since the server and client have so much common code, I package them together. If you have the client, you have the server. If you installed in Windows, you can hit the shortcut in your start menu. Otherwise, go straight to 'server' or 'server.exe' or 'server.pyw' in your installation directory. The program will first try to take port 45870 for its administration interface, so make sure that is free. Open your firewall as appropriate.
## set up the client { id="setting_up_the_client" }
In the _services->manage services_ dialog, add a new 'hydrus server administration service' and set up the basic options as appropriate. If you are running the server on the same computer as the client, its hostname is 'localhost'.
In order to set up the first admin account and an access key, use 'init' as a registration token. This special registration token will only work to initialise this first super-account.
!!! danger "YOU'LL WANT TO SAVE YOUR ACCESS KEY IN A SAFE PLACE"
If you lose your admin access key, there is no way to get it back, and if you are not sqlite-proficient, you'll have to restart from the beginning by deleting your server's database files.
If the client can't connect to the server, it is either not running or you have a firewall/port-mapping problem. If you want a quick way to test the server's visibility, just put `https://host:port` into your browser (make sure it is https! http will not work)--if it is working, your browser will probably complain about its self-signed https certificate. Once you add a certificate exception, the server should return some simple html identifying itself.
## set up the server { id="setting_up_the_server" }
You should have a new submenu, 'administrate services', under 'services', in the client gui. This is where you control most server and service-wide stuff.
_admin->your server->manage services_ lets you add, edit, and delete the services your server runs. Every time you add one, you will also be added as that service's first administrator, and the admin menu will gain a new entry for it.
## making accounts { id="making_accounts" }
Go _admin->your service->create new accounts_ to create new registration tokens. Send the registration tokens to the users you want to give these new accounts. A registration token will only work once, so if you want to give several people the same account, they will have to share the access key amongst themselves once one of them has registered the account. (Or you can register the account yourself and send them all the same access key. Do what you like!)
Go _admin->manage account types_ to add, remove, or edit account types. Make sure everyone has at least downloader (get_data) permissions so they can stay synchronised.
You can create as many accounts of whatever kind you like. Depending on your usage scenario, you may want to have all uploaders, one uploader and many downloaders, or just a single administrator. There are many combinations.
## ??? { id="have_fun" }
The most important part is to have fun! There are no losers on the INFORMATION SUPERHIGHWAY.
## profit { id="profit" }
I honestly hope you can get some benefit out of my code, whether just as a backup or as part of a far more complex system. Please mail me your comments as I am always keen to make improvements.
## btw, how to backup a repo's db { id="backing_up" }
All of a server's files and options are stored in its accompanying .db file and respective subdirectories, which are created on first startup (just like with the client). To backup or restore, you have two options:
* Shut down the server, copy the database files and directories, then restart it. This is the only way, currently, to restore a db.
* In the client, hit admin->your server->make a backup. This will lock the db server-side while it makes a copy of everything server-related to `server_install_dir/db/server_backup`. When the operation is complete, you can ftp/batch-copy/whatever the server\_backup folder wherever you like.
## OMG EVERYTHING WENT WRONG { id="hell" }
If you get to a point where you can no longer boot the repository, try running SQLite Studio and opening server.db. If the issue is simple--like manually changing the port number--you may be in luck. Send me an email if it is tricky.
Remember that everything is breaking all the time. Make regular backups, and you'll minimise your problems.

13
docs/support.md Normal file
View File

@ -0,0 +1,13 @@
---
title: financial support
---
# can I contribute to hydrus development? { id="support" }
I do not expect anything from anyone. I'm amazed and grateful that anyone wants to use my software and share tags with others. I enjoy the feedback and work, and I hope to keep putting completely free weekly releases out as long as there is more to do.
That said, as I have developed the software, several users have kindly offered to contribute money, either as thanks for a specific feature or just in general. I kept putting the thought off, but I eventually got over my hesitance and set something up.
I find the tactics of most internet fundraising very distasteful, especially when they promise something they then fail to deliver. I much prefer the 'if you like me and would like to contribute, then please do, meanwhile I'll keep doing what I do' model. I support several 'put out regular free content' creators on Patreon in this way, and I get a lot out of it, even though I have no direct reward beyond the knowledge that I helped some people do something neat.
If you feel the same way about my work, I've set up a simple Patreon page [here](https://www.patreon.com/hydrus_dev). If you can help out, it is deeply appreciated.

30
docs/wine.md Normal file
View File

@ -0,0 +1,30 @@
---
title: running in wine
---
# running a client or server in wine
Several Linux and macOS users have found success running hydrus with Wine. Here is a post from a Linux dude:
---
Some things I picked up on after extended use:
* Wine is kinda retarded sometimes, do not try to close the window by pressing the red close button, while in fullscreen.
* It will just "go through" it, and do whatever to whats behind it.
* Flash do work, IF you download the internet explorer version, and install it through wine.
* Hydrus is selfcontained, and portable. That means that one instance of hydrus do not know what another is doing. This is great if you want different installations for different things.
* Some of the input fields behave a little wonky. Though that may just be standard Hydrus behavior.
* Mostly everything else works fine. I was able to connect to the test server and view there. Only thing I need to test is the ability to host a server.
Installation process:
1. Get a standard Wine installation.
2. Download the latest hydrus .zip file.
3. Unpack it with your chosen zip file opener, in the chosen folder. Do not need to be in the wine folder.
4. Run it with wine, either though the file manager, or though the terminal.
5. For Flash support install the IE version through wine.
---
If you get the client running in Wine, please let me know how you get on!

View File

@ -4,14 +4,13 @@ repo_name: hydrusnetwork/hydrus
use_directory_urls: false
nav:
- index.md
- Help:
- Getting Started:
- introduction.md
- getting_started_installing.md
- getting_started_files.md
- getting_started_tags.md
- getting_started_downloading.md
- getting_started_ratings.md
- Getting Started:
- introduction.md
- getting_started_installing.md
- getting_started_files.md
- getting_started_tags.md
- getting_started_downloading.md
- getting_started_ratings.md
- PTR:
- access_keys.md
- PTR.md
@ -20,16 +19,27 @@ nav:
- adding_new_downloaders.md
- getting_started_subscriptions.md
- filtering duplicates: duplicates.md
- Advanced:
- advanced_siblings.md
- advanced_parents.md
- advanced.md
- reducing_lag.md
- database_migration.md
- launch_arguments.md
- Advanced:
- advanced_siblings.md
- advanced_parents.md
- advanced.md
- reducing_lag.md
- database_migration.md
- launch_arguments.md
- ipfs.md
- local_booru.md
- server.md
- Alternate Installations:
- docker.md
- wine.md
- running_from_source.md
- API: client_api.md
- changelog.md
- Misc:
- faq.md
- privacy.md
- contact.md
- support.md
- changelog.md
theme:
name: material
@ -46,6 +56,7 @@ theme:
- content.tabs.link
- navigation.top
- search.suggest
- content.code.annotate
#- navigation.indexes
icon: