Reset WordPress Post Query to default

Your problem is your custom query. Do not use variables that is used by default by WordPress. $posts and $post is WordPress reserved global variables. Change $post to a unique variable, something like $posts_query.

When using get_posts and you need to setup postdata to make use of template tags, you have no choiche but to use $post as setup_postdata() needs $post to be passed to it. This breaks the main query $post global, so you need to reset that once done. This is done with wp_reset_postdata().

Just a note on your code, template tags are not available by default when usng get_posts, so you need to add setup_postdata( $post ); inside your foreach loop to make the use of template tags available

Your custom query should look something like this

$posts_query = get_posts( 'YOUR ARGUMENTS' );
if ( $posts_query ) {
    foreach ( $posts_query as $post ) {
        setup_postdata( $post ); 

        // You can now use template tags like the_title() and the_content()

    }
    wp_reset_postdata();
}