Friday, December 29, 2023

3D Printing Geography

When I set about this I wanted to 3D print a model of a golf course for a friend. "How hard could this be?" I thought. Turns out... harder than I expected. This post walks through the entirety of what I tried through the process. If you want you can skip to the end where I walk you through the steps I followed to make my final print.


The first step is getting the tools for the job. So of course I did a lot of searching to find out what other people had done. I found this Reddit post which suggested using Equator to do the job. Despite putting in my credit card number for a free trial - I couldn't get it to work. (Maybe it was because something was broken and it was in the end of year holiday period.) 

Then, I found this post on medium that led me down a number of paths - only one of which I ended up taking in the long run! It suggested using OpenTopography to get the data, LASTools to convert the LIDAR data into a digital elevation model (DEM), and then QGIS to convert the DEM into an .STL for printing.

So first I go to OpenTopography, which provides freely accessible datasets, but... some of them are restricted for educational use only. You need a .edu email address, and I don't have one. So I continue searching. 

There are plenty of other locations for this data, and the good news if you are in the US, is that the US Geological Survey has the USGS Lidar Explorer which allows you to find where Lidar coverage is, and actually download the data. You can draw a box around your area of interest (AOI) and it will give you data to download for it. 

Now with data in hand, I ran the las2dem tool from LASTools against my dataset. And while I was able to get it to run, I got this warning:

WARNING: unlicensed. over 1.5 million points. inserting black diagonal.

Sure enough, LASTools was able to convert the data into a DEM, but it also made lines across the print which certainly reduced its realism. I fired off an email to the LASTools makers to see if they had any licensing for hobbyist use, but kept moving forward.

So, then I get QGIS installed - which is a free GIS swiss army knife of tools. Spoiler alert, QGIS is where I ended up doing all of the work in the long run. I could drag my DEM into QGIS and see it, generate a "hillshade" which makes it a little easier to visualize, but then also install the plugin called "DEMto3D" which allows you to convert the DEM into an .STL file for 3D printing. I found this terrific video on youtube that walks you through the process of using this plug-in, and I fully recommend you watch the video.


So, I'm through the process - generated a .STL, and printed it, and... was totally underwhelmed. The diagonal line is distracting, the trees are too pointy, the shape is laying at an awkward angle on a base that is square, there is a lot of stuff in the print I don't want... it's just not awesome.  


But that's why we keep trying things and learning. So now let's get on with the ACTUAL process I followed for the final product:
  • Use the USGS Lidar Explorer to download all of the original LIDAR scans that covered my AOI
  • Import all the LIDAR data into QGIS (it aligned them together since the GPS information for the location was built into each file). In QGIS' advanced processing menu, in the Point cloud data management section, used the merge tool to pull the 6 files covering my area into one single dataset.
  • In QGIS, rotate the maps so that you get your AOI as rectangular as possible to minimize wasted space.
  • In QGIS, create a new Shapefile layer and draw yourself a polygon (ideally rectangle) around your AOI. Make sure to toggle editing of your shapefile off and save the file before continuing.
  • In QGIS' advanced processing menu, in the Point cloud data management section, used the Clip tool to clip my merged dataset down to just my AOI.
  • In QGIS advanced processing menu, in the Point cloud conversion section, used the Export to raster feature. This did what las2dem did without the ugly diagonal lines. The "with triangulation" mode seems to get higher resolution but that wasn't actually helpful for my 3d print.
  • Use QGIS DEMto3D plugin to generate the .STL files. (I ended up using the tiling feature to do a large print. You enter the size of the final object, and the tiling will split that object for you.) Note that I found that adjusting the vertical exaggeration last was best using this plugin. I ended up doing 1.3x exaggeration for my golf course print.
  • Print! I ended up doing standard resolution and printing took a long time and a lot of filament! 10-15% infill is plenty.

Sunday, June 27, 2021

Raspberry PI VPN with 2-Factor Authentication

(Edited 1/19/2022 with some changes to make sure it works on Buster / other linux distributions with sec-linux. The new stuff is in purple.)

It took me a while but I finally found someone that had solved this. I am linking the solution. However, typing in a password and following it up with the one-time-password (OTP) is *extremely* user unfriendly. Anything that is hard to do to make better security actually makes worse security. Instead my approach protects the private keys with a password, and you then only use the OTP as the user's password each login.

So, here is the process. Assuming you have pivpn already installed and working with an OpenVPN configuration.

  1. Install google authenticator on the pi: sudo apt-get install libpam-google-authenticator
  2. Edit your openvpn server configuration: sudo nano /etc/openvpn/server.conf and add plugin /usr/lib/openvpn/openvpn-plugin-auth-pam.so openvpn (to use google authenticator) and reneg-sec 0 (to not reconnect every x minutes as the password changes every few seconds).
    • NOTE: This will make this server configuration only work with OTP. If you have accounts that will just be using passwords then you will need to have a separate server configuration and separate port for that. Info on how to do that is here.
    • NOTE 2: If you are on Buster, or some version of Linux where the openvpn-plugin-auth-pam.so is not in that location, you should link it into that location. For example in Buster, this would be the command you would run to create the appropriate link: sudo ln -s /usr/lib/arm-linux-gnueabihf/openvpn/plugins/openvpn-plugin-auth-pam.so /usr/lib/openvpn/openvpn-plugin-auth-pam.so 
  3. Create a pam.d openvpn profile: sudo cp /etc/pam.d/common-account /etc/pam.d/openvpn
  4. Edit it sudo nano /etc/pam.d/openvpn to add this line at the end: auth required pam_google_authenticator.so
  5. Newer versions of linux with sec-linux use a more strict sandboxing config in systemd which interferes with google-authenticator. To get past this, we will need to edit /lib/systemd/system/openvpn@.service and remove this line to make sure it can read the .google_authenticator files in the home directories of the accounts we create:
    ProtectHome=true
  6. Now run sudo service openvpn restart to reload the conf change.
Now, create your user. For this to work you will use system accounts (accounts you use to log to your raspberry like 'pi'). You can create as many account as you with the sudo adduser username command. The user's password really doesn't matter. Once you've created the user:
  1. login as the user on the raspberry sudo su - username (replace username with the actual username)
  2. run the google-authenticator command and follow the instructions (save the barcode url for next step, or import it directly on the user's device at that time)
  3. Type exit to get out of that user's shell and return to your own. 
  4. Executing google-authenticator adds a file .google_authenticator in the user’s home directory. This file must have no rights except read for the user, so run sudo chmod 400 /home/username/.google_authenticator (change to the correct username)
  5. create a pivpn account with the exact same name as the user : pivpn -a Note: the username must be the same than the system account. (The original directions suggest doing this with no password; It is safer to use a password to protect the private key. The password used here will need to be communicated safely to the user)
  6. edit the freshly created username.ovpn file and add the lines auth-user-pass (to tell the client to request username and password on connection) and reneg-sec 0 (to not reconnect every x minutes as the password changes every few seconds). And comment out the auth-nocache line by putting a # at the front of it. (This will keep the connection from re-negotiating every 60 minutes which is not good for an always-on VPN.)
Now, just install your .OVPN file on your client. (You can save the private key password if your client supports it, or require prompting for it every time.) Use the barcode URL generated earlier to show the QR Code for import into your authenticator app on your mobile device, and profit! 

Login with the same username and the OTP as the password. (The private key password being the one used when you created the account with the pivpn -a command.) You're now using multifactor authentication!. Something you know (the private key password) and something you have (your authenticator app which is a one-time-password generator).

Thursday, August 20, 2020

Autoparked AWS Instance

--This post is a draft and is a work in progress--

Goal: An AWS instance that runs, is trustworthy, easy to access, but also shuts down when isn't needed, and doesn't cost extra when it isn't running.

Tools: ddclient (dyndns client), letsencrypt (free certificates), AWS Instance Scheduler

1) set up aws to get a public ip which isn't default https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/TroubleshootingInstancesConnecting.html
- Create new VPC
- Create new Internet Gateway (in VPCs), attach it to the new VPC
- Create new Subnet
- On the Route Table tab of new subnet, verify that there is a route with 0.0.0.0/0 as the destination and the internet gateway for your VPC as the target. If not, choose Route Tables->your route table->Edit routes. Choose Add route, use 0.0.0.0/0 as the destination and the internet gateway as the target. For IPv6, choose Add route, use ::/0 as the destination and the internet gateway as the target then save.

2) install ddclient
sudo apt-get install ddclient

edit /etc/ddclient.conf

daemon=300
syslog=yes
use=cmd
cmd='curl -s http://169.254.169.254/latest/meta-data/public-ipv4'

protocol=googledomains
login=value-from-google
password='value-from-google'
DOMAINNAME.com

protocol=googledomains
login=value-from-google
password='value-from-google'
SUB.DOMAINNAME.com

protocol=googledomains
login=value-from-google
password='value-from-google'
ANOTHERDOMAINNAME.com

ddclient -syslog -noquiet -verbose -force
to ensure the registration goes well
now you can set up your SSH instance to connect to ubuntu@domain.name with your private key

3) install letsencrypt
sudo apt-get install letsencrypt
certbot certonly -d DOMAINNAME.com -d SUB.DOMAINNAME.com -d ANOTHERDOMAINNAME.com --manual --preferred-challenges dns --expand

Follow the instructions and add the required TXT records in Google Domains... wait a while (at least a couple minutes) before continuing. You should get the certificates.

(More work to be done to let this be automatically renewable - sudo certbot renew should do it).


...Profit?

Saturday, October 06, 2018

Amazon Fire Improvement

So you have a cheap Amazon Fire tablet, and you want to make it better... but you keep forgetting how to do it.


  1. Get the play store.
    1. Google Account Manager
    2. Google Services Framework
    3. Google Play Services
      1. or this one for the 2017 or later version of the Fire
    4. Google Play Store
  2. Remove the lockscreen ads.
    1. download this 
    2. adb shell pm install -r -d /sdcard/Download/com.amazon.unifiedsharefacebook.apk
    3. adb shell
      1. run-as com.amazon.unifiedsharefacebook 
      2. pm hide com.amazon.kindle.kso
      3. exit
    4. adb shell settings put global LOCKSCREEN_AD_ENABLED 0
    5. adb shell settings put global ksoHash 0
  3. Install a different launcher.
    1. https://github.com/BaronKiko/LauncherHijack/releases
    2. Remember to enable Accessibility Service through "Settings -> Accessibility -> To detect home button press" or nothing is going to happen
  4. Install other apps
    1. To use Google Contacts install this too
    2. Make sure you install Gmail
  5. Remove other unnecessary system apps.
    1. adb shell pm install -r -d /sdcard/Download/com.amazon.unifiedsharefacebook.apk
    2. adb shell
      1. run-as com.amazon.unifiedsharefacebook 
      2. id
        1. ensure id is not 2000
        2. then you can do pm hide for any apps you want to remove.
      3. pm hide com.amazon.kindle.kso
      4. pm hide com.amazon.dee.app
      5. pm hide com.amazon.avod
      6. pm hide com.audible.application.kindle
      7. pm hide com.goodreads.kindle
      8. pm hide com.amazon.zico
      9. pm hide com.amazon.venezia
      10. pm hide com.amazon.kindle
      11. pm hide com.amazon.webapp
      12. pm hide com.amazon.windowshop
      13. pm hide com.washingtonpost.rainbow
      14. pm hide com.android.contacts
      15. pm hide com.android.email
      16. pm hide com.amazon.geo.client.maps
      17. pm hide com.amazon.cloud9.kids
      18. pm hide com.amazon.ags.app
      19. pm hide com.android.calendar
      20. pm hide com.amazon.kindle.otter.oobe.forced.ota
      21. pm hide com.amazon.kcp.tutorial
      22. pm hide com.amazon.kor.demo
      23. pm hide com.amazon.socialplatform
      24. pm hide com.amazon.advertisingidsettings
      25. pm hide com.amazon.calculator
      26. pm hide com.amazon.client.metrics
      27. pm hide com.android.music
      28. pm hide com.amazon.dp.contacts
      29. pm hide com.amazon.dp.fbcontacts
      30. pm hide com.amazon.webview
      31. pm hide com.amazon.pm
      32. pm hide com.android.protips
      33. pm hide com.amazon.kindle.personal_video
      34. pm hide com.amazon.precog
      35. pm hide com.amazon.weather
      36. pm hide com.amazon.kindle.otter.oobe
      37. pm hide com.android.onetimeinitializer
      38. pm hide org.mopria.printplugin
      39. pm hide com.amazon.mp3
      40. pm hide com.amazon.photos.importer
      41. pm hide com.kingsoft.office.amz
      42. pm hide com.amazon.cloud9


Saturday, October 28, 2017

Congress

The idea behind Congress (our House and Senate):

"chosen body of citizens, whose wisdom may best discern the true interest of their country, and whose patriotism and love of justice will be least likely to sacrifice it to temporary or partial considerations."

(James Madison, Federalist Papers #10)

Monday, November 17, 2014

Extended use of Microsoft Trials

Like many people, the discontinuation of Microsoft's Technet Subscriptions made my job at times a little more difficult. It is nice to be able to spin up a server to test something out without worrying about continually paying for it (or remembering to shut it down) on Amazon AWS. And Microsoft made 180-day trials of server operating systems in their Evaluation Center.

In my case, I am duplicating a customer's 24-server system with 7 of my own virtual machines hosted internally. These are just test servers so I can walk people through the exact mouse clicks and commands they need to run to be successful in the unlikely event they call me with a question. For this purpose, buying 7 licenses alone is a non-starter and would make the effort useless.

So I wondered to myself, how can I keep using one of these 180-day trials for more than 180 days. Assuming non-production use, of course. At first I tried just backing up the complete system and restoring it to a newly installed trial. Unfortunately, it also restored the activation status of the machine, and it didn't get me any closer to my goal.

It has taken me a few tries but I've finally found the solution, at least for Windows 2008 R2.

You'll need:

  • The evaluation CD/DVD of the system you're using.
  • Available storage space to store complete system backup(s)
  • Ability to share that storage space through Windows sharing (\\server\share style)


So this is the process that worked for me.

  1. Install the Windows Server Backup feature on the system nearing expiration.
  2. Make a complete Windows System Backup (Bare Metal) to the windows share dedicated for backup storage.
  3. Shut down the system nearing expiration, hopefully for the last time.
  4. Use the evaluation CD/DVD to create a new 180-day trial system. Go through the entire installation process and get to standard Windows. Go ahead and activate it to get the 180 day timer running.
  5. Reboot the new system and hit F8 while it is booting. Choose "Directory Services Restore Mode" as your boot choice. This will boot you into a special version of Safe Mode
  6. Install the Windows Server Backup feature on the new system
  7. Restore from the share. You will get a warning indicating that this installation is not meant for this system. You will get another warning about if communication with the share has problems during restoration your new system may be unusable. Accept both warnings, it's non-production anyway.
  8. Reboot the system as required after the restoration is completed
  9. Reactivate windows on the new system. You should again see 180 days available.
Hopefully this will help someone. Or at least be someplace I remind myself of how I did it.

Saturday, March 01, 2014

BeagleBone Black Adventures

SSH Isn't Working

Remove the file /etc/dropbear/dropbear_rsa_host_key and then reboot the device.

PyUSB Doesn't Exist

Having trouble getting PyUSB or PySerial running on your BeagleBone Black? You've probably seen that you need to run "opkg install python-pyusb". And then you see that there is no such available package.

The answer is a simple one. "opkg update". This will update your list of available packages. Then try the above command and you should have more success.

Friday, October 26, 2012

Archiving Important Events

My friends are having a baby today. They asked me to buy a copy of today's paper so that they could have it to remember what was going on in the world on that date. I did.

Then, I thought, why wouldn't you want to memorialize more than just one local paper to find out what was going on? You see, the awesome Newseum has a site where they share all of today's front pages from over 800 newspapers worldwide. Note that the Newseum indicates the following:
Anyone seeking permission to use a front page must credit the Newseum and contact the newspaper directly for permission. U.S. copyright laws apply.
I think fair use doctrine wouldn't have a problem with you saving these images personally in an electronic baby book - but they shouldn't be shared or put up on a web page.

So, here's what I did. I used FireFox browser with the FoxySpider plugin, and a regex-capable text editor (in my case, TextWrangler).


  1. Install FireFox and the FoxySpider plugin if you haven't already. Go into the FoxySpider preferences and uncheck the "Limit gallery to X thumbnails" box.
  2. Go to the Newseum front pages site, and click the link to show All front pages.
  3. Right-click the page and choose FoxySpider - Advanced Filters
    • In Crawl pages within this URL I modified it slightly to ensure it captured only the linked pages with images - currently this is http://www.newseum.org/todaysfrontpages/hr.asp*
    • Click Start!
    • In the generated page of thumbnails, choose "Select all files" from the drop down and click the Download Files button. Choose a folder to save all the files to.
    • Close the FoxySpider tab after it's done.
  4. Right-click the page again and choose Save Page As... and save it as a .html file in the same folder as you saved the images to. For the type, choose "Web page, complete" so that it keeps the thumbnails.
  5. Open the .html file in your text editor and perform the following replacement (as of today's date, at least):
    • Find: href="http://www\.newseum\.org/todaysfrontpages/hr\.asp\?fpVname=([A-Z]*_[A-Z]*)&ref_pge=gal&b_pge=1"
    • Replace: href="\1.jpg"
    • Matching: (check the Grep checkbox)
  6. Save the file. Now you have a local copy of the Newseum's Today's Front Pages page linked to the local copy of each image you've saved using FoxySpider.
Again to be clear this should be for personal, non-commercial uses only. I think it would have been cool to see every front page from the day I was born without having to go to the Library and checking out the microfiche.

Thursday, September 13, 2012

Taking my stand against the Boy Scouts of America

Below is an image of the letter and badge I just sent back to the Boy Scouts of America. I have copied the complete text below.


September 13, 2012
Boy Scouts of America
National Executive Board
1325 Walnut Hill Lane
PO Box 152079
Irving, TX 75015-2079

Enclosed is my Eagle Scout badge. I do not feel comfortable holding this award because the organization which it represents has strayed too far from the ideals which I embraced while in scouting. This letter explains the two issues that have caused me to take this action. First, there is a dissonance between my experience as a member of the Boy Scouts of America (BSA) and the current actions of the organization. Second, the BSA has made a generalization about morality which is simply untrue.

To be clear, I am not disavowing my award, or the BSA organization. My time spent as a Boy Scout was invaluable to me. I have wrestled with this issue for the last seven years, and I have not come to this decision lightly. I felt it was necessary to take some action, rather than just patiently wait for mindsets and policies to change. Based on the insight I gained as a scout, I feel it is now my duty to defend members of our society from the BSA organization.

As a Boy Scout and leader from Troop 673 from Great Falls, Virginia, I earned the rank of Eagle Scout in December, 1992. The enclosed badge was presented to me during an Eagle Scout Court of Honor in March 1993. I spent nearly six of my most valuable and formative years as a Boy Scout, and after earning Eagle I served my troop an additional year and a half as assistant scoutmaster. I was selected as a Patrol Leader before I started high school; this put me in the sometimes awkward position of leading boys older than me. This experience taught me many lessons about how to lead others, including: 
  • Making the differences between people fade into the background so we could work together
  • Looking out for, and supporting individuals who are in physical, mental, or emotional trouble
  • How to offer help to others without making them feel less valuable
Happily married for the last 14 years, I am blessed with three children including one son, Brian. Since his birth seven years ago, I have entertained warm thoughts of guiding him through scouting – hoping to watch him grow through the same experiences I did, and helping at every turn.

Sadly, my excitement turned to concern and discontent as I learned of the discrimination which is currently practiced organizationally by the BSA. I was stunned by the realization that the organization that taught me how to bring people together was now dividing people and causing unnecessary pain. In 1991, the Boy Scouts of America issued this statement:
We believe homosexual conduct is inconsistent with the requirement in the Scout oath that a Scout be morally straight and in the Scout law that a Scout be clean in word and deed. Homosexuals do not provide a desirable role model for Scouts.
This statement is as puzzling as it is troubling. It is in clear dissonance with the organization I remember. The BSA taught me how to see through our differences, how to help others, and helped set my moral compass.

While I am not a homosexual, in both my personal and professional life I count homosexual men and women as some of my closest friends. I have never experienced anything which would lead me to believe that “Homosexuals do not provide a desirable role model for Scouts.” I have known many boys (and men) who were/are not desirable role models, but this has nothing to do with their actual or professed sexual orientation – it has everything to do with their moral character and how they treat other people. Moral character is not based or dependent on sexual orientation.

Homosexuality is not a “disease” which can be transmitted from one to another. It does not cause people to become rapists, pedophiles, or sexual deviants. It is a difference between the way people see and experience love, and nothing else. Homosexuality is not something to be afraid of, and not something that people should be ostracized for. While some religions consider homosexuality a sin, it is not universally accepted as such. The BSA should not use religion as a reason to justify discrimination.

Somewhere between 2% and 10% of our population is homosexual. I know our world would be improved if everyone took the time to befriend a homosexual and learn how to interact with him or her as a person, rather than as someone who is different.

I have been a practicing member of the United Methodist church my entire life; my wife is an organist at our church, and my family is involved in many ministries and attends worship regularly. The United Methodist church has a resolution called “Opposition to Homophobia and Heterosexism” which states:
Therefore, be it resolved, that The United Methodist Church strengthen its advocacy of the eradication of sexism by opposing all forms of violence or discrimination based on gender, gender identity, sexual practice, or sexual orientation;
Through participation in Bible study and prayerful consideration of the will of God in my life, I find it difficult to understand why any organization which claims a Duty to God and professes to uphold the teachings of Jesus could act in a discriminatory manner toward any of God’s children. As it reads in Matthew 22:37-40,
[Jesus] said to him,’ “You shall love the Lord your God with all your heart, and with all your soul, and with all your mind.” This is the greatest and first commandment. And a second is like it: “You shall love your neighbor as yourself.” On these two commandments hang all the law and the prophets.’
I took an oath as a Boy Scout which was repeated as a centerpiece of the Eagle Scout court of honor. On my honor, I will do my best to do my duty to God and my country and to obey the Scout Law; to help other people at all times; to keep myself physically strong, mentally awake and morally straight. To comply with this oath and do my duty to God, I believe that I need to uphold this commandment. It is God’s will that we love our neighbors as ourselves – which means we must not discriminate, marginalize, or otherwise look down upon our brothers and sisters.

I am conflicted between the experience of my reality and what strikes me as a faulty and misaligned position of the BSA. The current position is born of ignorance and popular pressure instead of honoring what scouts learn and practice in their lives. How can I continue to honor God and align myself with BSA with this hurtful and morally repugnant position in place? It is, ironically, my duty as an Eagle Scout to help other people at all times and therefore to defend homosexuals against the hateful actions of BSA.

I look forward to the day when the BSA restores the honor of my Eagle Scout badge by reversing its membership policies and official statements regarding homosexuality. On that day, please return my badge to the address below.

Sincerely,

Peter M. Hesse
Eagle Scout, Troop 673, March 1993

Thursday, April 12, 2012

Reducing size of Windows 7's WinSXS folder

To reduce size of your \Windows\winsxs folder, run this in command prompt as admin: 


dism /online /cleanup-image /spsuperseded /hidesp



This will get rid of extra files which have been superseded by a service pack update. If you installed using a slipstreamed installation (in other words, it already had a service pack integrated when you installed Windows) you should use this command (replacing D: with the drive your Windows folder is installed on):



dism /image:D: /cleanup-image /spsuperseded /hidesp