This server was down all weekend after I attempted reformatting the 60GB SSD to be a data storage drive and managed to break the boot process. Even though the operating system was moved to the RAID 1 MicroSD array, the bootloader was still on the SSD. Apparently this worked due to the SSD having a small EFI system partition at the beginning of it. When I had first got the thin client and went to repartition and format the drive for Linux, I left the EFI system partition intact but I never did anything with it, and everything worked without me having to do some special EFI setup so I had assumed that it wasn't actually necessary. After much messing around, it turns out that this wasn't the case.
Luckily I have a USB drive set up as a live rescue Linux install, so I was able to boot from that (even though it doesn't contain any EFI info) and attempt to figure out why the thin client wouldn't let me boot from any of the internal drives. Through the messing around I discovered that I actually can boot from the MicroSD cards (previously I had thought this wasn't the case) so I decided to update everything so that the system would no longer need the SSD to boot from. This should come in handy in the future when I replace the SSD with some regular hard disk storage drives.
After some digging around I ended up finding this post: https://blog.roberthallam.org/2020/05/psa-dell-wyse-3040-uses-fallback-efi-location/ which shed some light on the situation. Turns out you need to install the bootloader with EFI options set or else the system will refuse to boot. I think it worked from the SSD previously because even though I repartitioned the drive, I never actually blew away the data on the first partition, so the motherboard was able to read the information it needed from there and run the bootloader.
After having my AWS account compromised I decided to take all my stuff out of the cloud and go back to hosting my own server at home. I used to have an old Dell machine but I haven't had it running in a few years. I had planned to replace it with a Banana Pi single board computer but never got around to building a case for all of the hardware. Then I had the thought to get a recycled thin client computer, figuring they would be pretty cheap and I could install Linux on it like a regular PC. So I went on ebay and found this for $50:
A Dell Wyse 7010 Thin Client
I like the idea of re-purposing old hardware, and this little box would be a compact and 100% quiet server that I could sit on my desk and not be annoyed by constant fan whirring.
Here is a JavaScript function that calculates the civil twilight start/end and sunrise/sunset times for a given latitude, longitude, and unix timestamp. (Note: the timestamp is in seconds, so the result of Date.now() needs to be divided by 1000 for this to work properly.) I use this function along with IP geolocation to change the colors on the page as the visitor's day shifts from daylight to dark.
This code was adapted from the information provided here.
function calcSunset( lat, lon, timestamp )
{
function fmod( f, d )
{
let i = Math.floor( f / d );
return f - i * d;
}
function deg2rad( r )
{
return r * ( Math.PI / 180 );
}
function rad2deg( r )
{
return r * 180 / Math.PI;
}
let jDate = ( timestamp / 86400.0 ) + 2440587.5;
let n = Math.round( ( jDate - 2451545 - 0.0009 ) - ( lon / 360 ) );
let jp = 2451545 + 0.0009 + ( lon / 360 ) + n;
let rjp = jp;
let l = null;
let jTrans = null;
let M = null;
for( let i = 0; i < 5; i++ )
{
M = fmod( 357.5291 + 0.98560028 * ( rjp - 2451545 ), 360 );
let C = ( 1.9148 * Math.sin( deg2rad( M ) ) ) + ( 0.0200 * Math.sin( deg2rad( 2 * M ) ) ) + ( 0.0003 * Math.sin( deg2rad( 3 * M ) ) );
l = fmod( M + 102.9372 + C + 180, 360 );
jTrans = jp + ( 0.0053 * Math.sin( deg2rad( M ) ) ) - ( 0.0069 * Math.sin( deg2rad( 2 * l ) ) );
rjp = jTrans;
}
let theta = rad2deg( Math.asin( Math.sin( deg2rad( l ) ) * Math.sin( deg2rad( 23.45 ) ) ) );
let H = rad2deg( Math.acos( ( Math.sin( deg2rad( -0.83 ) ) - Math.sin( deg2rad( lat ) ) * Math.sin( deg2rad( theta ) ) ) / ( Math.cos( deg2rad( lat ) ) * Math.cos( deg2rad( theta ) ) ) ) );
let jpp = 2451545 + 0.0009 + (( H + lon ) / 360 ) + n;
let jSet = jpp + ( 0.0053 * Math.sin( deg2rad( M ) ) ) - ( 0.0069 * Math.sin( deg2rad( 2 * l ) ) );
let jRise = jTrans - ( jSet - jTrans );
let sunset = ( jSet - 2440587.5 ) * 86400;
let sunrise = ( jRise - 2440587.5 ) * 86400;
H = rad2deg( Math.acos( ( Math.sin( deg2rad( -6.83 ) ) - Math.sin( deg2rad( lat ) ) * Math.sin( deg2rad( theta ) ) ) / ( Math.cos( deg2rad( lat ) ) * Math.cos( deg2rad( theta ) ) ) ) );
jpp = 2451545 + 0.0009 + (( H + lon ) / 360 ) + n;
jSet = jpp + ( 0.0053 * Math.sin( deg2rad( M ) ) ) - ( 0.0069 * Math.sin( deg2rad( 2 * l ) ) );
jRise = jTrans - ( jSet - jTrans );
let eveningTwilight = ( jSet - 2440587.5 ) * 86400;
let morningTwilight = ( jRise - 2440587.5 ) * 86400;
return {
morningTwilight: morningTwilight;
sunrise: sunrise;
sunset: sunset;
eveningTwilight: eveningTwilight;
};
}