I’ve crawled the largest english-language recipes sites, and parsed the results into JSON. Go do fun things with a database of 140,000 recipes!
Not much to say here, just a link: https://archive.org/details/recipes-en-201706
I’ve crawled the largest english-language recipes sites, and parsed the results into JSON. Go do fun things with a database of 140,000 recipes!
Not much to say here, just a link: https://archive.org/details/recipes-en-201706
Today’s project was a hard drive carrying case. I wanted something to securely store hard drives. When I looked around on ebay and amazon, I saw some nice cases and some crappy plastic molded ones. Even the terrible ones were at least $50, so I made my own.
I bought a used ammo case at the rather excellent local army surplus store. Then I padded all sides. I had spare EVA foam “puzzle piece” style mats from a gym setup lying around. I cut out the pieces with scissors. That’s it. I was expecting more steps, but nothing needed glued in place. I was planning on adding inserts for the empty slots, but it seems secure enough. If you’re making one, you could also glue the top onto the lid, so you don’t have to take it out manually.
I’m on Linux, and here’s what I did to get the Adafruit Pro Trinket (3.3V version) to work. I think most of this should work for other Adafruit boards as well. I’m on Arch Linux, but other distros will be similar, just find the right paths for everything. Your version of udev may vary on older distros especially.
Copy the hardware profiles to your Arduino install. pacman -Ql arduino
shows me that I should be installing to /usr/share/aduino. You can find the files you need at their source (copy the entire folder) or the same thing is packaged inside of the IDE installs.
cp adafruit-git /usr/share/arduino/adafruit
Re-configure “ATtiny85” to work with avrdude. On arch, pacman -Ql arduino | grep "avrdude.conf
says I should edit /usr/share/arduino/hardware/tools/avr/etc/avrdude.conf. Paste this revised “t85” section into avrdude.conf (credit to the author)
Install a udev rule so you can program the Trinket Pro as yourself (and not as root).
# /etc/udev/rules.d/adafruit-usbtiny.rules
SUBSYSTEM=="usb", ATTR{product}=="USBtiny", ATTR{idProduct}=="0c9f", ATTRS{idVendor}=="1781", MODE="0660", GROUP="arduino"
Add yourself as an arduino group user so you can program the device with usermod -G arduino -a <username>
. Reload the udev rules and log in again to refresh the groups you’re in. Close and re-open the Arduino IDE if you have it open to refresh the hardware rules.
Sources:
http://www.bacspc.com/2015/07/28/arch-linux-and-trinket/
http://andijcr.github.io/blog/2014/07/31/notes-on-trinket-on-ubuntu-14.04/
Summary of “the life-changing magic of tidying up”:
Marie Kondo writes the “KonMari” method. The book ends up being as much about her mistakes in learning how to tidy as it is about how to tidy. The book conveys a certain positive energy that makes me want to recommend it, but the author also brings that energy in reaction to a kind of previous stress which accompanied tidying, which she does not seem to have completely dropped–if you are mysteriously anxious and feel you MUST discard everything after reading her book, this may be why.
The primary point she makes is meant to cure it: Decide what to keep and what to discard by physically touching each item, and asking if it brings you joy.
The rest of the method:
Marie Kondo’s best advice is realizations from her past mistakes–the sort of methods which seems reasonable to try, but end up being wrong for subtle reasons. They are:
She also has encountered her clients making mistakes. For each category of things (clothes, books, etc) there are many reasons clients may not want to throw something out. Most of the book is meant to illustrate why these things are useless, and why throwing them out is okay and will make you happier.
The fun part is that many clients were more confident and more in touch with what they valued and who they wanted once they had only possessions they loved.
Bolded text in the book
za3k.com was the site of a DDoS attack. I’m pretty sure this was because my wordpress installation was compromised, and the hacker who took control of my server was herself DDoSed.
More updates to come, but the short story is that I’ll be formalizing my install and eventually containerizing + hardening everything
This one’s a quickie. Just a second of my config to record all bash commands to a file (.bash_eternal_history) forever. The default bash HISTFILESIZE is 500. Setting it to a non-numeric value will make the history file grow forever (although not your actual history size, which is controlled by HISTSIZE).
I do this in addition:
#~/.bash.d/eternal-history
# don't put duplicate lines in the history
HISTCONTROL=ignoredups
# append to the history file, don't overwrite it
shopt -s histappend
# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
HISTFILESIZE=infinite
# Creates an eternal bash log in the form
# PID USER INDEX TIMESTAMP COMMAND
export HISTTIMEFORMAT="%s "
PROMPT_COMMAND="${PROMPT_COMMAND:+$PROMPT_COMMAND ; }"'echo $$ $USER \
"$(history 1)" >> ~/.bash_eternal_history'
Today I’m going to walk through a setup on how to archive all web (HTTP/S) traffic passing over your Linux desktop. The basic approach is going to be to install a proxy which records traffic. It will record the traffic to WARC files. You can’t proxy non-HTTP traffic (for example, chat or email) because we’re using an HTTP proxy approach.
The end result is pretty slow for reasons I’m not totally sure of yet. It’s possible warcproxy isn’t streaming results.
Install the server
# pip install warcproxy
Make a warcprox user to run the proxy as.
# useradd -M --shell=/bin/false warcprox
Make a root certificate. You’re going to intercept HTTPS traffic by pretending to be the website, so if anyone gets ahold of this, they can fake being every website to you. Don’t give it out.
# mkdir /etc/warcprox
# cd /etc/warcprox
# sudo openssl genrsa -out ca.key 409
# sudo openssl req -new -x509 -key ca.key -out ca.crt
# cat ca.crt ca.key >ca.pem
# chown root:warcprox ca.pem ca.key
# chmod 640 ca.pem ca.key
Set up a directory where you’re going to store the WARC files. You’re saving all web traffic, so this will get pretty big.
# mkdir /var/warcprox
# chown -R warcprox:warcprox /var/warcprox
Set up a boot script for warcproxy. Here’s mine. I’m using supervisorctl rather than systemd.
#/etc/supervisor.d/warcprox.ini
[program:warcprox]
command=/usr/bin/warcprox -p 18000 -c /etc/warcprox/ca.pem --certs-dir ./generated-certs -g sha1
directory=/var/warcprox
user=warcprox
autostart=true
autorestart=unexpected
Set up any browers, etc to use localhost:18000 as your proxy. You could also do some kind of global firewall config. Chromium in particular was pretty irritating on Arch Linux. It doesn’t respect $http_proxy, so you have to pass it separate options. This is also a good point to make sure anything you don’t want recorded BYPASSES the proxy (for example, maybe large things like youtube, etc).
I’m opening the NNTP server at nttp.za3k.com (TLS or unencrypted) to the public. These are the newsgroups currently on it. It is virtually zero-traffic (no users, but also users post little).
If you don’t have a news reader, Thunderbird can do the job, or take a look at the list here.
art.agency.applied
art.autonomy
art.programming
news.announce.newusers
news.discuss
research.fai
research.fai.decisiontheory
research.math
research.philosophy
research.strategy
research.xrisk
talk.math
talk.news
talk.other
talk.personal
talk.philosophy
talk.programming
talk.psychology
talk.reading
talk.reading.collaborative
talk.science
talk.writing
talk.writing.collaborative
test.posts
This expands on my previous post about how to set up an email server.
We’re going to set up a few spam filters in Dovecot under Debian. We’re going to use Sieve, which lets the user set up whichever filters they want. However, we’re going to run a couple pre-baked spam filters regardless of what the user sets up.
Install Sieve.
sudo apt-get install dovecot-sieve dovecot-managesieved
Add Sieve to Dovecot
# /etc/dovecot/dovecot.conf
# Sieve and ManageSieve
protocols = $protocols sieve
protocol lmtp {
mail_plugins = $mail_plugins sieve
}
service managesieve-login {
inet_listener sieve {
port = 4190
}
}
protocol sieve {
managesieve_logout_format = bytes ( in=%i : out=%o )
}
plugin {
# Settings for the Sieve and ManageSieve plugin
sieve = file:~/sieve;active=~/.dovecot.sieve
sieve_before = /etc/dovecot/sieve.d/
sieve_dir = ~/sieve # For old version of ManageSieve
#sieve_extensions = +vnd.dovecot.filter
#sieve_plugins = sieve_extprograms
}
Install and update SpamAssassin, a heuristic perl script for spam filtering.
sudo apt-get install spamasssassin
sudo sa-update
# /etc/default/spamassassin
ENABLED=1
#CRON=1 # Update automatically
# /etc/spamassassin/local.cf
report_safe 0 # Don't modify headers
sudo service spamassassin start
There’s a lot of custom configuration and training you should do to get SpamAssassin to accurately categorize what you consider spam. I’m including a minimal amount here. The following will train SpamAssassin system-wide based on what users sort into spam folders.
#!/bin/sh
# /etc/cron.daily/spamassassin-train
all_folders() {
find /var/mail/vmail -type d -regextype posix-extended -regex '.*/cur|new$'
}
all_folders | grep "Spam" | sa-learn --spam -f - >/dev/null 2>/dev/null
all_folders | grep -v "Spam" | sa-learn --ham -f - >/dev/null 2>/dev/null
Make Postfix run SpamAssassin as a filter, so that it can add headers as mail comes in.
# /etc/postfix/master.cf
smtp inet n - - - - smtpd
-o content_filter=spamassassin
# ...
spamassassin unix - n n - - pipe user=debian-spamd argv=/usr/bin/spamc -f -e /usr/sbin/sendmail -oi -f ${sender} ${recipient}
sudo service postfix restart
Add SpamAssassin to Sieve. Dovecot (via Sieve) will now move messages with spam headers from SpamAssassin to your spam folder. Make sure you have a “Spam” folder and that it’s set to autosubscribe.
# /etc/dovecot/sieve.d/spam-assassin.sieve
require ["fileinto"];
# Move spam to spam folder
if header :contains "X-Spam-Flag" "YES" {
fileinto "Spam";
# Stop here - if there are other rules, ignore them for spam messages
stop;
}
cd /etc/dovecot/sieve.d
sudo sievec spam-assassin.sieve
Restart Dovecot
sudo service dovecot restart
Test spam. The GTUBE is designed to definitely get rejected. Set the content of your email to this:
XJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X
You should also be able to create user-defined filters in Sieve, via the ManageSieve protocol. I tested this using a Sieve thunderbird extension. You’re on your own here.
I’m posting my email setup here. The end result will:
Note: My set up is pretty standard, except that rDNS for smtp.za3k.com resolves to za3k.com because I only have one IP. You may need to change your hostnames if you’re using mail.example.com or smtp.example.com.
On to the install!
Install debian packages
sudo apt-get install postfix # Postfix \
dovecot-core dovecot-imapd dovecot-lmtpd # Dovecot \
postgresql dovecot-pgsql postfix-pgsql # Postgres \
opendkim opendkim-tools # DKIM
Set up security. smtp.za3k.com cert is at /etc/certs/zak3.com.pem, the key is at /etc/ssl/private/smtp.za3k.com.key. dhparams for postfix are at /etc/postfix/dhparams.pem. (If you need a certificate and don’t know how to get one, you can read Setting up SSL certificates using StartSSL)
Install Postfix
# /etc/postfix/master.cf
smtp inet n - - - - smtpd
submission inet n - - - - smtpd
-o syslog_name=postfix/submission
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes
-o smtpd_reject_unlisted_recipient=no
-o milter_macro_daemon_name=ORIGINATING
# /etc/postfix/main.cf additions
# TLS parameters
smtpd_tls_cert_file=/etc/ssl/certs/smtp.za3k.com.pem
smtpd_tls_key_file=/etc/ssl/private/smtp.za3k.com.key
smtpd_use_tls=yes
smtpd_tls_mandatory_protocols=!SSLv2,!SSLv3
smtp_tls_mandatory_protocols=!SSLv2,!SSLv3
smtpd_tls_protocols=!SSLv2,!SSLv3
smtp_tls_protocols=!SSLv2,!SSLv3
smtpd_tls_exclude_ciphers = aNULL, eNULL, EXPORT, DES, RC4, MD5, PSK, aECDH, EDH-DSS-DES-CBC3-SHA, EDH-RSA-DES-CDC3-SHA, KRB5-DE5, CBC3-SHA
# Relay and recipient settings
myhostname = za3k.com
myorigin = /etc/mailname
mydestination = za3k.com, smtp.za3k.com, localhost.com, localhost
relayhost =
mynetworks_style = host
mailbox_size_limit = 0
inet_interfaces = all
smtpd_relay_restrictions = permit_mynetworks,
permit_sasl_authenticated,
reject_unauth_destination
alias_maps = hash:/etc/aliases
local_recipient_maps = $alias_maps
mailbox_transport = lmtp:unix:private/dovecot-lmtp
Install Dovecot
# /etc/dovecot/dovecot.cf
mail_privileged_group = mail # Local mail
disable_plaintext_auth = no
protocols = imap
ssl=required
ssl_cert = </etc/ssl/certs/imap.za3k.com.pem
ssl_key = </etc/ssl/private/imap.za3k.com.key
# IMAP Folders
namespace {
inbox = yes
mailbox Trash {
auto = create
special_use = \Trash
}
mailbox Drafts {
auto = no
special_use = \Drafts
}
mailbox Sent {
auto = subscribe
special_use = \Sent
}
mailbox Spam {
auto = subscribe
special_use = \Junk
}
}
# Expunging / deleting mail should FAIL, use the lazy_expunge plugin for this
namespace {
prefix = .EXPUNGED/
hidden = yes
list = no
location = maildir:~/expunged
}
mail_plugins = $mail_plugins lazy_expunge
plugin {
lazy_expunge = .EXPUNGED/
}
# /etc/postfix/main.cf
# SASL authentication is done through Dovecot to let users relay mail
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
Set up the database and virtual users. Commands
# Create the user vmail for storing virtual mail
# vmail:x:5000:5000::/var/mail/vmail:/usr/bin/nologin
groupadd -g 5000 vmail
mkdir /var/mail/vmail
useradd -M -d /var/mail/vmail --shell=/usr/bin/nologin -u 5000 -g vmail vmail
chown vmail:vmail /var/mail/vmail
chmod 700 /var/mail/vmail
psql -U postgres
; Set up the users
CREATE USER 'postfix' PASSWORD 'XXX';
CREATE USER 'dovecot' PASSWORD 'XXX';
; Create the database
CREATE DATABASE email;
\connect email
; Set up the schema
CREATE TABLE aliases (
alias text NOT NULL,
email text NOT NULL
);
CREATE TABLE users (
username text NOT NULL,
domain text NOT NULL,
created timestamp with time zone DEFAULT now(),
password text NOT NULL
);
REVOKE ALL ON TABLE aliases FROM PUBLIC;
GRANT ALL ON TABLE aliases TO postfix;
GRANT ALL ON TABLE aliases TO dovecot;
REVOKE ALL ON TABLE users FROM PUBLIC;
GRANT ALL ON TABLE users TO dovecot;
GRANT ALL ON TABLE users TO postfix;
# /etc/dovecot/dovecot.conf
# Since we're giving each virtual user their own directory under /var/mail/vmail, just use that directly and not a subdirectory
mail_location = maildir:~/
# /etc/dovecot/dovecot-sql.conf defines the DB queries used for authorization
passdb {
driver = sql
args = /etc/dovecot/dovecot-sql.conf
}
userdb {
driver = prefetch
}
userdb {
driver = sql
args = /etc/dovecot/dovecot-sql.conf
}
# /etc/postfix/main.cf
pgsql:/etc/postfix/pgsql-virtual-aliases.cf
local_recipient_maps = pgsql:/etc/postfix/pgsql-virtual-mailbox.cf
# /etc/postfix/pgsql-virtual-aliases.cf
# hosts = localhost
user = postfix
password = XXXXXX
dbname = email
query = SELECT email FROM aliases WHERE alias='%s'
# /etc/postfix/pgsql-virtual-mailbox.cf
# hosts = localhost
user = postfix
password = XXXXXX
dbname = email
query = SELECT concat(username,'@',domain,'/') as email FROM users WHERE username='%s'
# /etc/dovecot/dovecot-sql.conf
driver = pgsql
connect = host=localhost dbname=email user=dovecot password=XXXXXX
default_pass_scheme = SHA512
password_query = SELECT \
CONCAT(username,'@',domain) as user, \
password, \
'vmail' AS userdb_uid, \
'vmail' AS userdb_gid, \
'/var/mail/vmail/%u' as userdb_home \
FROM users \
WHERE concat(username,'@',domain) = '%u';
user_query = SELECT username, \
CONCAT('maildir:/var/mail/vmail/',username,'@',domain) as mail, \
'/var/mail/vmail/%u' as home, \
'vmail' as uid, \
'vmail' as gid \
FROM users \
WHERE concat(username,'@',domain) = '%u';
Set up users. Example user creation:
# Generate a password
$ doveadm pw -s sha512 -r 100
Enter new password: ...
Retype new password: ...
{SHA512}.............................................................==
psql -U dovecot -d email
; Create a user za3k@za3k.com
mail=# INSERT INTO users (
username,
domain,
password
) VALUES (
'za3k',
'za3k.com'
'{SHA512}.............................................................==',
);
Set up aliases/redirects. Example redirect creation:
psql -U dovecot -d email
; Redirect mail from foo@example.com to bar@example.net
mail=# INSERT INTO users ( email, alias ) VALUES (
'bar@example.net',
'foo@example.com'
);
Test setup locally by hand. Try using TELNET. Test remote setup using STARTSSL. This is similar to the previous step, but to start the connection use:
openssl s_client -connect smtp.za3k.com:587 -starttls smtp
Make sure to test email to addresses at your domain or that you’ve set up (final destination), and emails you’re trying to send somewhere else (relay email)
A small digression: port 25 is used for unencrypted email and support STARTTLS, 587 is used for STARTTLS only, and 465 (obsolete) is used for TLS. My ISP, Comcast, blocks access to port 25 on outgoing traffic.
Make sure you’re not running an open relay at http://mxtoolbox.com/diagnostic.aspx
Set up DKIM (DomainKeys Identified Mail). DKIM signs outgoing mail to show that it’s from your server, which helps you not get flagged as spam.
None of these files or folders exist to begin with in debian.
# Add to /etc/opendkim.conf
KeyTable /etc/opendkim/KeyTable
SigningTable /etc/opendkim/SigningTable
ExternalIgnoreList /etc/opendkim/TrustedHosts
InternalHosts /etc/opendkim/TrustedHosts
LogWhy yes
# /etc/opendkim/TrustedHosts
127.0.0.1
[::1]
localhost
za3k.com
smtp.za3k.com
mkdir -p /etc/opendkim/keys/za3k.com
cd /etc/opendkim/keys/za3k.com
opendkim-genkey -s default -d za3k.com
chown opendkim:opendkim default.private
# /etc/opendkim/KeyTable
default._domainkey.za3k.com za3k.com:default:/etc/opendkim/keys/za3k.com/default.private
# /etc/opendkim/SigningTable
za3k.com default._domainkey.za3k.com
Display the DNS public key to set in a TXT record with:
# sudo cat /etc/opendkim/keys/za3k.com/default.txt
default._domainkey IN TXT ( "v=DKIM1; k=rsa; "
"p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCggdv3OtQMek/fnu+hRrHYZTUcpUFcSGL/+Sbq+GffR98RCgabx/jjPJo3HmqsB8czaXf7yjO2UiSN/a8Ae6/yu23d7hyTPUDacatEM+2Xc4/zG+eAlAMQOLRJeo3z53sNiq0SmJET6R6yH4HCv9VkuS0TQczkvME5hApft+ZedwIDAQAB" ) ; ----- DKIM
# My registrar doesn't support this syntax so it ends up looking like:
$ dig txt default._domainkey.za3k.com txt
default._domainkey.za3k.com. 10800 IN TXT "v=DKIM1\; k=rsa\; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCggdv3OtQMek/fnu+hRrHYZTUcpUFcSGL/+Sbq+GffR98RCgabx/jjPJo3HmqsB8czaXf7yjO2UiSN/a8Ae6/yu23d7hyTPUDacatEM+2Xc4/zG+eAlAMQOLRJeo3z53sNiq0SmJET6R6yH4HCv9VkuS0TQczkvME5hApft+ZedwIDAQAB"
# Uncomment in /etc/default/opendkim
SOCKET="inet:12345@localhost" # listen on loopback on port 12345
# /etc/postfix/main.cf
# DKIM
milter_default_action = accept
milter_protocol = 6
smtpd_milters = inet:localhost:12345
non_smtpd_milters = inet:localhost:12345
Set up SPF (Sender Policy Framework). SPF explains to other services which IPs can send email on your behalf. You can set up whatever policy you like. A guide to the syntax is at: http://www.openspf.org/SPF_Record_Syntax. Mine is
@ 10800 IN TXT "v=spf1 +a:za3k.com +mx:za3k.com ~all"
You should also be verifying this on your end as part of combating spam, but as far as outgoing mail all you need to do is add a TXT record to your DNS record.
Set your rDNS (reverse DNS) if it’s not already. This should point at the same hostname reported by Postfix during SMTP. This will be handled by whoever assigns your IP address (in my case, my hosting provider).
Set up DMARC. DMARC declares your policy around DKIM being mandatory. You can set up whatever policy you like. Mine is
_dmarc 10800 IN TXT "v=DMARC1;p=reject;aspf=s;adkim=s;pct=100;rua=mailto:postmaster@za3k.com"
My sources writing this:
Takeaways